New upstream version 7.0.5+ds
authorIOhannes m zmölnig <zmoelnig@umlautS.umlaeute.mur.at>
Sat, 28 Jan 2023 18:41:09 +0000 (19:41 +0100)
committerIOhannes m zmölnig <zmoelnig@umlautS.umlaeute.mur.at>
Sat, 28 Jan 2023 18:41:09 +0000 (19:41 +0100)
546 files changed:
BREAKING-CHANGES.txt
CMakeLists.txt
ChangeList.txt
README.md
docs/ARA.md
docs/Accessibility.md
docs/doxygen/Doxyfile
docs/doxygen/process_source_files.py
examples/Assets/AudioLiveScrollingDisplay.h
examples/Assets/DSPDemos_Common.h
examples/Assets/DemoUtilities.h
examples/Audio/AudioLatencyDemo.h
examples/Audio/AudioPlaybackDemo.h
examples/Audio/AudioRecordingDemo.h
examples/Audio/MPEDemo.h
examples/DemoRunner/Builds/Android/app/CMakeLists.txt
examples/DemoRunner/Builds/Android/app/build.gradle
examples/DemoRunner/Builds/Android/app/src/main/AndroidManifest.xml
examples/DemoRunner/Builds/Android/app/src/main/assets/AudioLiveScrollingDisplay.h
examples/DemoRunner/Builds/Android/app/src/main/assets/DSPDemos_Common.h
examples/DemoRunner/Builds/Android/app/src/main/assets/DemoUtilities.h
examples/DemoRunner/Builds/Android/build.gradle
examples/DemoRunner/Builds/Android/gradle/wrapper/gradle-wrapper.properties
examples/DemoRunner/Builds/LinuxMakefile/Makefile
examples/DemoRunner/Builds/MacOSX/DemoRunner.xcodeproj/project.pbxproj
examples/DemoRunner/Builds/MacOSX/Info-App.plist
examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj
examples/DemoRunner/Builds/VisualStudio2017/DemoRunner_App.vcxproj.filters
examples/DemoRunner/Builds/VisualStudio2017/resources.rc
examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj
examples/DemoRunner/Builds/VisualStudio2019/DemoRunner_App.vcxproj.filters
examples/DemoRunner/Builds/VisualStudio2019/resources.rc
examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj
examples/DemoRunner/Builds/VisualStudio2022/DemoRunner_App.vcxproj.filters
examples/DemoRunner/Builds/VisualStudio2022/resources.rc
examples/DemoRunner/Builds/iOS/DemoRunner.xcodeproj/project.pbxproj
examples/DemoRunner/Builds/iOS/Info-App.plist
examples/DemoRunner/DemoRunner.jucer
examples/DemoRunner/JuceLibraryCode/JuceHeader.h
examples/GUI/AnimationAppDemo.h
examples/GUI/ImagesDemo.h
examples/GUI/OpenGLAppDemo.h
examples/GUI/VideoDemo.h
examples/Plugins/ARAPluginDemo.h
examples/Plugins/DSPModulePluginDemo.h
examples/Plugins/MultiOutSynthPluginDemo.h
examples/Plugins/SamplerPluginDemo.h
examples/Utilities/InAppPurchasesDemo.h
examples/Utilities/MultithreadingDemo.h
examples/Utilities/SystemInfoDemo.h
extras/AudioPerformanceTest/Builds/Android/app/CMakeLists.txt
extras/AudioPerformanceTest/Builds/Android/app/build.gradle
extras/AudioPerformanceTest/Builds/Android/app/src/main/AndroidManifest.xml
extras/AudioPerformanceTest/Builds/Android/build.gradle
extras/AudioPerformanceTest/Builds/Android/gradle/wrapper/gradle-wrapper.properties
extras/AudioPerformanceTest/Builds/LinuxMakefile/Makefile
extras/AudioPerformanceTest/Builds/MacOSX/AudioPerformanceTest.xcodeproj/project.pbxproj
extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj
extras/AudioPerformanceTest/Builds/VisualStudio2022/AudioPerformanceTest_App.vcxproj.filters
extras/AudioPerformanceTest/Builds/iOS/AudioPerformanceTest.xcodeproj/project.pbxproj
extras/AudioPerformanceTest/Source/Main.cpp
extras/AudioPerformanceTest/Source/MainComponent.h
extras/AudioPluginHost/AudioPluginHost.jucer
extras/AudioPluginHost/Builds/Android/app/CMakeLists.txt
extras/AudioPluginHost/Builds/Android/app/build.gradle
extras/AudioPluginHost/Builds/Android/app/src/main/AndroidManifest.xml
extras/AudioPluginHost/Builds/Android/app/src/main/assets/AudioLiveScrollingDisplay.h
extras/AudioPluginHost/Builds/Android/app/src/main/assets/DSPDemos_Common.h
extras/AudioPluginHost/Builds/Android/app/src/main/assets/DemoUtilities.h
extras/AudioPluginHost/Builds/Android/build.gradle
extras/AudioPluginHost/Builds/Android/gradle/wrapper/gradle-wrapper.properties
extras/AudioPluginHost/Builds/LinuxMakefile/Makefile
extras/AudioPluginHost/Builds/MacOSX/AudioPluginHost.xcodeproj/project.pbxproj
extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj
extras/AudioPluginHost/Builds/VisualStudio2017/AudioPluginHost_App.vcxproj.filters
extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj
extras/AudioPluginHost/Builds/VisualStudio2019/AudioPluginHost_App.vcxproj.filters
extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj
extras/AudioPluginHost/Builds/VisualStudio2022/AudioPluginHost_App.vcxproj.filters
extras/AudioPluginHost/Builds/iOS/AudioPluginHost.xcodeproj/project.pbxproj
extras/AudioPluginHost/Source/UI/PluginWindow.h
extras/BinaryBuilder/Builds/LinuxMakefile/Makefile
extras/BinaryBuilder/Builds/MacOSX/BinaryBuilder.xcodeproj/project.pbxproj
extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj
extras/BinaryBuilder/Builds/VisualStudio2022/BinaryBuilder_ConsoleApp.vcxproj.filters
extras/Build/CMake/JUCECheckAtomic.cmake
extras/Build/CMake/JUCEModuleSupport.cmake
extras/Build/CMake/JUCEUtils.cmake
extras/Build/juce_build_tools/juce_build_tools.h
extras/Build/juceaide/CMakeLists.txt
extras/Build/juceaide/Main.cpp
extras/NetworkGraphicsDemo/Builds/Android/app/CMakeLists.txt
extras/NetworkGraphicsDemo/Builds/Android/app/build.gradle
extras/NetworkGraphicsDemo/Builds/Android/app/src/main/AndroidManifest.xml
extras/NetworkGraphicsDemo/Builds/Android/build.gradle
extras/NetworkGraphicsDemo/Builds/Android/gradle/wrapper/gradle-wrapper.properties
extras/NetworkGraphicsDemo/Builds/LinuxMakefile/Makefile
extras/NetworkGraphicsDemo/Builds/MacOSX/NetworkGraphicsDemo.xcodeproj/project.pbxproj
extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj
extras/NetworkGraphicsDemo/Builds/VisualStudio2022/NetworkGraphicsDemo_App.vcxproj.filters
extras/NetworkGraphicsDemo/Builds/iOS/NetworkGraphicsDemo.xcodeproj/project.pbxproj
extras/NetworkGraphicsDemo/NetworkGraphicsDemo.jucer
extras/NetworkGraphicsDemo/Source/Demos.h
extras/Projucer/Builds/LinuxMakefile/Makefile
extras/Projucer/Builds/MacOSX/Info-App.plist
extras/Projucer/Builds/MacOSX/Projucer.xcodeproj/project.pbxproj
extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj
extras/Projucer/Builds/VisualStudio2017/Projucer_App.vcxproj.filters
extras/Projucer/Builds/VisualStudio2017/resources.rc
extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj
extras/Projucer/Builds/VisualStudio2019/Projucer_App.vcxproj.filters
extras/Projucer/Builds/VisualStudio2019/resources.rc
extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj
extras/Projucer/Builds/VisualStudio2022/Projucer_App.vcxproj.filters
extras/Projucer/Builds/VisualStudio2022/resources.rc
extras/Projucer/CMakeLists.txt
extras/Projucer/JuceLibraryCode/JuceHeader.h
extras/Projucer/Projucer.jucer
extras/Projucer/Source/Application/jucer_AutoUpdater.cpp
extras/Projucer/Source/Application/jucer_CommonHeaders.h
extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementPath.cpp
extras/Projucer/Source/ComponentEditor/PaintElements/jucer_PaintElementPath.h
extras/Projucer/Source/ComponentEditor/jucer_ComponentLayout.h
extras/Projucer/Source/ComponentEditor/jucer_JucerDocument.cpp
extras/Projucer/Source/ComponentEditor/jucer_PaintRoutine.h
extras/Projucer/Source/Project/UI/Sidebar/jucer_Sidebar.h
extras/Projucer/Source/Project/jucer_Project.cpp
extras/Projucer/Source/Project/jucer_Project.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Android.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_CodeBlocks.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_MSVC.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Make.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExport_Xcode.h
extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.cpp
extras/Projucer/Source/ProjectSaving/jucer_ProjectExporter.h
extras/Projucer/Source/Utility/Helpers/jucer_PresetIDs.h
extras/Projucer/Source/Utility/Helpers/jucer_TranslationHelpers.h
extras/Projucer/Source/Utility/PIPs/jucer_PIPGenerator.cpp
extras/Projucer/Source/Utility/UI/jucer_JucerTreeViewBase.h
extras/Projucer/Source/Utility/UI/jucer_SlidingPanelComponent.h
extras/UnitTestRunner/Builds/LinuxMakefile/Makefile
extras/UnitTestRunner/Builds/MacOSX/UnitTestRunner.xcodeproj/project.pbxproj
extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj
extras/UnitTestRunner/Builds/VisualStudio2017/UnitTestRunner_ConsoleApp.vcxproj.filters
extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj
extras/UnitTestRunner/Builds/VisualStudio2019/UnitTestRunner_ConsoleApp.vcxproj.filters
extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj
extras/UnitTestRunner/Builds/VisualStudio2022/UnitTestRunner_ConsoleApp.vcxproj.filters
extras/UnitTestRunner/UnitTestRunner.jucer
extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj
extras/WindowsDLL/Builds/VisualStudio2022/WindowsDLL_StaticLibrary.vcxproj.filters
modules/CMakeLists.txt
modules/juce_analytics/juce_analytics.h
modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp [new file with mode: 0644]
modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h
modules/juce_audio_basics/buffers/juce_AudioDataConverters.h
modules/juce_audio_basics/buffers/juce_AudioSampleBuffer.h
modules/juce_audio_basics/buffers/juce_FloatVectorOperations.cpp
modules/juce_audio_basics/buffers/juce_FloatVectorOperations.h
modules/juce_audio_basics/juce_audio_basics.cpp
modules/juce_audio_basics/juce_audio_basics.h
modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp [new file with mode: 0644]
modules/juce_audio_basics/midi/ump/juce_UMPIterator.h
modules/juce_audio_basics/midi/ump/juce_UMPView.h
modules/juce_audio_basics/midi/ump/juce_UMP_test.cpp
modules/juce_audio_basics/midi/ump/juce_UMPacket.h
modules/juce_audio_basics/mpe/juce_MPEInstrument.cpp
modules/juce_audio_basics/mpe/juce_MPEInstrument.h
modules/juce_audio_basics/mpe/juce_MPESynthesiser.cpp
modules/juce_audio_basics/mpe/juce_MPESynthesiser.h
modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp [new file with mode: 0644]
modules/juce_audio_basics/sources/juce_PositionableAudioSource.h
modules/juce_audio_basics/synthesisers/juce_Synthesiser.cpp
modules/juce_audio_basics/synthesisers/juce_Synthesiser.h
modules/juce_audio_basics/utilities/juce_GenericInterpolator.h
modules/juce_audio_basics/utilities/juce_SmoothedValue.h
modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.cpp
modules/juce_audio_devices/audio_io/juce_AudioDeviceManager.h
modules/juce_audio_devices/audio_io/juce_AudioIODevice.cpp
modules/juce_audio_devices/audio_io/juce_AudioIODevice.h
modules/juce_audio_devices/juce_audio_devices.cpp
modules/juce_audio_devices/juce_audio_devices.h
modules/juce_audio_devices/midi_io/juce_MidiDevices.cpp
modules/juce_audio_devices/midi_io/juce_MidiDevices.h
modules/juce_audio_devices/native/juce_android_Audio.cpp
modules/juce_audio_devices/native/juce_android_Midi.cpp
modules/juce_audio_devices/native/juce_android_Oboe.cpp
modules/juce_audio_devices/native/juce_android_OpenSL.cpp
modules/juce_audio_devices/native/juce_ios_Audio.cpp
modules/juce_audio_devices/native/juce_linux_ALSA.cpp
modules/juce_audio_devices/native/juce_linux_JackAudio.cpp
modules/juce_audio_devices/native/juce_mac_CoreAudio.cpp
modules/juce_audio_devices/native/juce_mac_CoreMidi.mm
modules/juce_audio_devices/native/juce_win32_ASIO.cpp
modules/juce_audio_devices/native/juce_win32_DirectSound.cpp
modules/juce_audio_devices/native/juce_win32_Midi.cpp
modules/juce_audio_devices/native/juce_win32_WASAPI.cpp
modules/juce_audio_devices/sources/juce_AudioSourcePlayer.cpp
modules/juce_audio_devices/sources/juce_AudioSourcePlayer.h
modules/juce_audio_formats/codecs/juce_AiffAudioFormat.cpp
modules/juce_audio_formats/codecs/juce_CoreAudioFormat.cpp
modules/juce_audio_formats/codecs/juce_FlacAudioFormat.cpp
modules/juce_audio_formats/codecs/juce_LAMEEncoderAudioFormat.cpp
modules/juce_audio_formats/codecs/juce_MP3AudioFormat.cpp
modules/juce_audio_formats/codecs/juce_OggVorbisAudioFormat.cpp
modules/juce_audio_formats/codecs/juce_WavAudioFormat.cpp
modules/juce_audio_formats/codecs/juce_WindowsMediaAudioFormat.cpp
modules/juce_audio_formats/format/juce_ARAAudioReaders.cpp
modules/juce_audio_formats/format/juce_ARAAudioReaders.h
modules/juce_audio_formats/format/juce_AudioFormatReader.cpp
modules/juce_audio_formats/format/juce_AudioFormatReader.h
modules/juce_audio_formats/format/juce_AudioSubsectionReader.cpp
modules/juce_audio_formats/format/juce_AudioSubsectionReader.h
modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.cpp
modules/juce_audio_formats/format/juce_BufferingAudioFormatReader.h
modules/juce_audio_formats/juce_audio_formats.h
modules/juce_audio_plugin_client/AAX/juce_AAX_Wrapper.cpp
modules/juce_audio_plugin_client/ARA/juce_ARA_Wrapper.cpp
modules/juce_audio_plugin_client/AUResources.r [deleted file]
modules/juce_audio_plugin_client/CMakeLists.txt [deleted file]
modules/juce_audio_plugin_client/LV2/juce_LV2TurtleDumpProgram.cpp
modules/juce_audio_plugin_client/LV2/juce_LV2_Client.cpp
modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterApp.cpp
modules/juce_audio_plugin_client/Standalone/juce_StandaloneFilterWindow.h
modules/juce_audio_plugin_client/Unity/juce_Unity_Wrapper.cpp
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.cpp
modules/juce_audio_plugin_client/VST/juce_VST_Wrapper.mm
modules/juce_audio_plugin_client/VST3/juce_VST3_Wrapper.cpp
modules/juce_audio_plugin_client/juce_audio_plugin_client.h
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r [deleted file]
modules/juce_audio_plugin_client/juce_audio_plugin_client_AU_2.mm
modules/juce_audio_plugin_client/juce_audio_plugin_client_Standalone.cpp
modules/juce_audio_plugin_client/utility/juce_CreatePluginFilter.h
modules/juce_audio_plugin_client/utility/juce_LinuxMessageThread.h
modules/juce_audio_plugin_client/utility/juce_PluginUtilities.cpp
modules/juce_audio_processors/format/juce_AudioPluginFormatManager.cpp
modules/juce_audio_processors/format_types/LV2_SDK/juce_lv2_config.h
modules/juce_audio_processors/format_types/juce_AudioUnitPluginFormat.mm
modules/juce_audio_processors/format_types/juce_LADSPAPluginFormat.cpp
modules/juce_audio_processors/format_types/juce_LV2Common.h
modules/juce_audio_processors/format_types/juce_LV2PluginFormat.cpp
modules/juce_audio_processors/format_types/juce_LV2SupportLibs.cpp
modules/juce_audio_processors/format_types/juce_VST3Common.h
modules/juce_audio_processors/format_types/juce_VST3Headers.h
modules/juce_audio_processors/format_types/juce_VST3PluginFormat.cpp
modules/juce_audio_processors/format_types/juce_VSTPluginFormat.cpp
modules/juce_audio_processors/juce_audio_processors.cpp
modules/juce_audio_processors/juce_audio_processors.h
modules/juce_audio_processors/processors/juce_AudioProcessor.cpp
modules/juce_audio_processors/processors/juce_AudioProcessor.h
modules/juce_audio_processors/processors/juce_AudioProcessorEditor.cpp
modules/juce_audio_processors/processors/juce_AudioProcessorGraph.cpp
modules/juce_audio_processors/processors/juce_AudioProcessorGraph.h
modules/juce_audio_processors/processors/juce_AudioProcessorListener.h
modules/juce_audio_processors/processors/juce_GenericAudioProcessorEditor.cpp
modules/juce_audio_processors/processors/juce_HostedAudioProcessorParameter.h
modules/juce_audio_processors/utilities/ARA/juce_ARADocumentController.cpp
modules/juce_audio_processors/utilities/ARA/juce_ARADocumentController.h
modules/juce_audio_processors/utilities/ARA/juce_ARAModelObjects.cpp
modules/juce_audio_processors/utilities/ARA/juce_ARAModelObjects.h
modules/juce_audio_processors/utilities/ARA/juce_ARAPlugInInstanceRoles.cpp
modules/juce_audio_processors/utilities/ARA/juce_ARAPlugInInstanceRoles.h
modules/juce_audio_processors/utilities/juce_AudioProcessorParameterWithID.h
modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.cpp
modules/juce_audio_processors/utilities/juce_AudioProcessorValueTreeState.h
modules/juce_audio_processors/utilities/juce_PluginHostType.cpp
modules/juce_audio_processors/utilities/juce_PluginHostType.h
modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h
modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp [new file with mode: 0644]
modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h
modules/juce_audio_utils/audio_cd/juce_AudioCDReader.h
modules/juce_audio_utils/gui/juce_AudioDeviceSelectorComponent.cpp
modules/juce_audio_utils/gui/juce_AudioThumbnail.cpp
modules/juce_audio_utils/gui/juce_AudioThumbnail.h
modules/juce_audio_utils/gui/juce_AudioThumbnailCache.cpp
modules/juce_audio_utils/gui/juce_AudioVisualiserComponent.cpp
modules/juce_audio_utils/gui/juce_AudioVisualiserComponent.h
modules/juce_audio_utils/gui/juce_MPEKeyboardComponent.h
modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.cpp
modules/juce_audio_utils/gui/juce_MidiKeyboardComponent.h
modules/juce_audio_utils/juce_audio_utils.h
modules/juce_audio_utils/native/juce_linux_AudioCDReader.cpp
modules/juce_audio_utils/native/juce_mac_AudioCDReader.mm
modules/juce_audio_utils/native/juce_win32_AudioCDReader.cpp
modules/juce_audio_utils/players/juce_AudioProcessorPlayer.cpp
modules/juce_audio_utils/players/juce_AudioProcessorPlayer.h
modules/juce_audio_utils/players/juce_SoundPlayer.cpp
modules/juce_audio_utils/players/juce_SoundPlayer.h
modules/juce_box2d/juce_box2d.h
modules/juce_core/containers/juce_Array.h
modules/juce_core/containers/juce_ArrayBase.cpp
modules/juce_core/containers/juce_ArrayBase.h
modules/juce_core/containers/juce_ElementComparator.h
modules/juce_core/containers/juce_Optional.h
modules/juce_core/containers/juce_Optional_test.cpp
modules/juce_core/containers/juce_OwnedArray.h
modules/juce_core/containers/juce_ReferenceCountedArray.h
modules/juce_core/containers/juce_Variant.cpp
modules/juce_core/files/juce_File.cpp
modules/juce_core/files/juce_FileSearchPath.cpp
modules/juce_core/files/juce_FileSearchPath.h
modules/juce_core/files/juce_common_MimeTypes.cpp
modules/juce_core/files/juce_common_MimeTypes.h
modules/juce_core/javascript/juce_Javascript.cpp
modules/juce_core/juce_core.cpp
modules/juce_core/juce_core.h
modules/juce_core/maths/juce_BigInteger.cpp
modules/juce_core/maths/juce_BigInteger.h
modules/juce_core/maths/juce_Expression.cpp
modules/juce_core/maths/juce_MathsFunctions.h
modules/juce_core/maths/juce_Range.h
modules/juce_core/memory/juce_ContainerDeletePolicy.h
modules/juce_core/memory/juce_HeapBlock.h
modules/juce_core/memory/juce_Memory.h
modules/juce_core/memory/juce_WeakReference.h
modules/juce_core/misc/juce_Functional.h
modules/juce_core/misc/juce_RuntimePermissions.h
modules/juce_core/native/juce_BasicNativeHeaders.h
modules/juce_core/native/juce_android_AndroidDocument.cpp
modules/juce_core/native/juce_android_JNIHelpers.cpp
modules/juce_core/native/juce_android_JNIHelpers.h
modules/juce_core/native/juce_android_Network.cpp
modules/juce_core/native/juce_android_RuntimePermissions.cpp
modules/juce_core/native/juce_android_SystemStats.cpp
modules/juce_core/native/juce_android_Threads.cpp
modules/juce_core/native/juce_linux_SystemStats.cpp
modules/juce_core/native/juce_linux_Threads.cpp
modules/juce_core/native/juce_mac_CFHelpers.h
modules/juce_core/native/juce_mac_Files.mm
modules/juce_core/native/juce_mac_Network.mm
modules/juce_core/native/juce_mac_ObjCHelpers.h
modules/juce_core/native/juce_mac_SystemStats.mm
modules/juce_core/native/juce_mac_Threads.mm
modules/juce_core/native/juce_native_ThreadPriorities.h [new file with mode: 0644]
modules/juce_core/native/juce_posix_NamedPipe.cpp
modules/juce_core/native/juce_posix_SharedCode.h
modules/juce_core/native/juce_win32_Files.cpp
modules/juce_core/native/juce_win32_SystemStats.cpp
modules/juce_core/native/juce_win32_Threads.cpp
modules/juce_core/network/juce_Socket.cpp
modules/juce_core/network/juce_URL.cpp
modules/juce_core/network/juce_URL.h
modules/juce_core/network/juce_WebInputStream.cpp
modules/juce_core/network/juce_WebInputStream.h
modules/juce_core/streams/juce_MemoryOutputStream.cpp
modules/juce_core/system/juce_CompilerSupport.h
modules/juce_core/system/juce_StandardHeader.h
modules/juce_core/system/juce_SystemStats.cpp
modules/juce_core/system/juce_SystemStats.h
modules/juce_core/system/juce_TargetPlatform.h
modules/juce_core/text/juce_CharacterFunctions.h
modules/juce_core/text/juce_LocalisedStrings.h
modules/juce_core/threads/juce_CriticalSection.h
modules/juce_core/threads/juce_HighResolutionTimer.cpp
modules/juce_core/threads/juce_HighResolutionTimer.h
modules/juce_core/threads/juce_Process.h
modules/juce_core/threads/juce_Thread.cpp
modules/juce_core/threads/juce_Thread.h
modules/juce_core/threads/juce_ThreadPool.cpp
modules/juce_core/threads/juce_ThreadPool.h
modules/juce_core/threads/juce_TimeSliceThread.cpp
modules/juce_core/threads/juce_TimeSliceThread.h
modules/juce_core/time/juce_RelativeTime.cpp
modules/juce_core/unit_tests/juce_UnitTestCategories.h
modules/juce_core/xml/juce_XmlElement.h
modules/juce_cryptography/encryption/juce_BlowFish.cpp
modules/juce_cryptography/juce_cryptography.h
modules/juce_data_structures/juce_data_structures.cpp
modules/juce_data_structures/juce_data_structures.h
modules/juce_data_structures/undomanager/juce_UndoableAction.cpp [new file with mode: 0644]
modules/juce_data_structures/undomanager/juce_UndoableAction.h
modules/juce_data_structures/values/juce_ValueTree.cpp
modules/juce_data_structures/values/juce_ValueTree.h
modules/juce_dsp/containers/juce_AudioBlock.h
modules/juce_dsp/containers/juce_AudioBlock_test.cpp
modules/juce_dsp/containers/juce_FixedSizeFunction.h
modules/juce_dsp/containers/juce_FixedSizeFunction_test.cpp
modules/juce_dsp/containers/juce_SIMDRegister.h
modules/juce_dsp/containers/juce_SIMDRegister_test.cpp
modules/juce_dsp/frequency/juce_Convolution.h
modules/juce_dsp/frequency/juce_Convolution_test.cpp
modules/juce_dsp/juce_dsp.cpp
modules/juce_dsp/juce_dsp.h
modules/juce_dsp/native/juce_fallback_SIMDNativeOps.h
modules/juce_dsp/native/juce_neon_SIMDNativeOps.cpp
modules/juce_dsp/native/juce_neon_SIMDNativeOps.h
modules/juce_dsp/processors/juce_DelayLine.h
modules/juce_dsp/processors/juce_FIRFilter.h
modules/juce_dsp/processors/juce_IIRFilter_Impl.h
modules/juce_dsp/processors/juce_ProcessorChain.h
modules/juce_dsp/processors/juce_StateVariableFilter.h
modules/juce_dsp/widgets/juce_WaveShaper.h
modules/juce_events/interprocess/juce_ConnectedChildProcess.cpp
modules/juce_events/interprocess/juce_NetworkServiceDiscovery.cpp
modules/juce_events/juce_events.h
modules/juce_events/messages/juce_ApplicationBase.cpp
modules/juce_events/native/juce_linux_Messaging.cpp
modules/juce_events/native/juce_win32_Messaging.cpp
modules/juce_events/native/juce_win32_WinRTWrapper.cpp
modules/juce_events/native/juce_win32_WinRTWrapper.h
modules/juce_events/timers/juce_Timer.cpp
modules/juce_graphics/colour/juce_Colour.h
modules/juce_graphics/contexts/juce_GraphicsContext.cpp
modules/juce_graphics/contexts/juce_LowLevelGraphicsContext.h
modules/juce_graphics/fonts/juce_Font.h
modules/juce_graphics/fonts/juce_TextLayout.h
modules/juce_graphics/geometry/juce_Point.h
modules/juce_graphics/geometry/juce_Rectangle.h
modules/juce_graphics/geometry/juce_RectangleList.h
modules/juce_graphics/juce_graphics.h
modules/juce_graphics/native/juce_freetype_Fonts.cpp
modules/juce_graphics/native/juce_linux_Fonts.cpp
modules/juce_graphics/native/juce_mac_CoreGraphicsContext.h
modules/juce_graphics/native/juce_mac_CoreGraphicsContext.mm
modules/juce_graphics/native/juce_win32_Direct2DGraphicsContext.cpp
modules/juce_graphics/native/juce_win32_DirectWriteTypeLayout.cpp
modules/juce_graphics/native/juce_win32_DirectWriteTypeface.cpp
modules/juce_graphics/native/juce_win32_Fonts.cpp
modules/juce_gui_basics/accessibility/juce_AccessibilityState.h
modules/juce_gui_basics/components/juce_Component.cpp
modules/juce_gui_basics/components/juce_Component.h
modules/juce_gui_basics/desktop/juce_Displays.h
modules/juce_gui_basics/filebrowser/juce_ContentSharer.cpp
modules/juce_gui_basics/filebrowser/juce_DirectoryContentsList.cpp
modules/juce_gui_basics/filebrowser/juce_FileBrowserComponent.cpp
modules/juce_gui_basics/filebrowser/juce_FileChooser.cpp
modules/juce_gui_basics/filebrowser/juce_FileChooser.h
modules/juce_gui_basics/filebrowser/juce_FileChooserDialogBox.h
modules/juce_gui_basics/filebrowser/juce_FileListComponent.cpp
modules/juce_gui_basics/filebrowser/juce_FileListComponent.h
modules/juce_gui_basics/filebrowser/juce_FileTreeComponent.cpp
modules/juce_gui_basics/juce_gui_basics.cpp
modules/juce_gui_basics/juce_gui_basics.h
modules/juce_gui_basics/keyboard/juce_KeyListener.h
modules/juce_gui_basics/keyboard/juce_ModifierKeys.h
modules/juce_gui_basics/keyboard/juce_TextInputTarget.h
modules/juce_gui_basics/layout/juce_Grid.cpp
modules/juce_gui_basics/layout/juce_SidePanel.cpp
modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V3.cpp
modules/juce_gui_basics/lookandfeel/juce_LookAndFeel_V4.cpp
modules/juce_gui_basics/menus/juce_PopupMenu.cpp
modules/juce_gui_basics/menus/juce_PopupMenu.h
modules/juce_gui_basics/misc/juce_JUCESplashScreen.cpp
modules/juce_gui_basics/mouse/juce_MouseInputSource.cpp
modules/juce_gui_basics/mouse/juce_PointerState.h
modules/juce_gui_basics/mouse/juce_TooltipClient.h
modules/juce_gui_basics/native/accessibility/juce_android_Accessibility.cpp
modules/juce_gui_basics/native/accessibility/juce_ios_Accessibility.mm
modules/juce_gui_basics/native/accessibility/juce_win32_Accessibility.cpp
modules/juce_gui_basics/native/accessibility/juce_win32_AccessibilityElement.cpp
modules/juce_gui_basics/native/accessibility/juce_win32_AccessibilityElement.h
modules/juce_gui_basics/native/accessibility/juce_win32_ComInterfaces.h
modules/juce_gui_basics/native/accessibility/juce_win32_UIAExpandCollapseProvider.h
modules/juce_gui_basics/native/accessibility/juce_win32_UIAInvokeProvider.h
modules/juce_gui_basics/native/accessibility/juce_win32_UIASelectionProvider.h
modules/juce_gui_basics/native/accessibility/juce_win32_UIATextProvider.h
modules/juce_gui_basics/native/java/app/com/rmsl/juce/ComponentPeerView.java
modules/juce_gui_basics/native/java/app/com/rmsl/juce/JuceContentProviderFileObserver.java
modules/juce_gui_basics/native/juce_android_ContentSharer.cpp
modules/juce_gui_basics/native/juce_android_FileChooser.cpp
modules/juce_gui_basics/native/juce_android_Windowing.cpp
modules/juce_gui_basics/native/juce_ios_ContentSharer.cpp
modules/juce_gui_basics/native/juce_ios_FileChooser.mm
modules/juce_gui_basics/native/juce_ios_UIViewComponentPeer.mm
modules/juce_gui_basics/native/juce_ios_Windowing.mm
modules/juce_gui_basics/native/juce_linux_Windowing.cpp
modules/juce_gui_basics/native/juce_mac_CGMetalLayerRenderer.h
modules/juce_gui_basics/native/juce_mac_FileChooser.mm
modules/juce_gui_basics/native/juce_mac_MainMenu.mm
modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm
modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h [new file with mode: 0644]
modules/juce_gui_basics/native/juce_mac_Windowing.mm
modules/juce_gui_basics/native/juce_win32_DragAndDrop.cpp
modules/juce_gui_basics/native/juce_win32_FileChooser.cpp
modules/juce_gui_basics/native/juce_win32_Windowing.cpp
modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h [new file with mode: 0644]
modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.cpp
modules/juce_gui_basics/native/x11/juce_linux_XWindowSystem.h
modules/juce_gui_basics/widgets/juce_ComboBox.cpp
modules/juce_gui_basics/widgets/juce_ListBox.cpp
modules/juce_gui_basics/widgets/juce_Slider.cpp
modules/juce_gui_basics/widgets/juce_TableHeaderComponent.cpp
modules/juce_gui_basics/widgets/juce_TableHeaderComponent.h
modules/juce_gui_basics/widgets/juce_TableListBox.cpp
modules/juce_gui_basics/widgets/juce_TextEditor.cpp
modules/juce_gui_basics/widgets/juce_TextEditor.h
modules/juce_gui_basics/widgets/juce_TreeView.cpp
modules/juce_gui_basics/widgets/juce_TreeView.h
modules/juce_gui_basics/windows/juce_ComponentPeer.cpp
modules/juce_gui_basics/windows/juce_ComponentPeer.h
modules/juce_gui_basics/windows/juce_MessageBoxOptions.h
modules/juce_gui_basics/windows/juce_ThreadWithProgressWindow.cpp
modules/juce_gui_basics/windows/juce_ThreadWithProgressWindow.h
modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp
modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp [new file with mode: 0644]
modules/juce_gui_basics/windows/juce_VBlankAttachement.h [new file with mode: 0644]
modules/juce_gui_extra/code_editor/juce_CodeEditorComponent.cpp
modules/juce_gui_extra/embedding/juce_ActiveXControlComponent.h
modules/juce_gui_extra/embedding/juce_NSViewComponent.h
modules/juce_gui_extra/juce_gui_extra.cpp
modules/juce_gui_extra/juce_gui_extra.h
modules/juce_gui_extra/misc/juce_AnimatedAppComponent.cpp
modules/juce_gui_extra/misc/juce_AnimatedAppComponent.h
modules/juce_gui_extra/misc/juce_PushNotifications.cpp
modules/juce_gui_extra/misc/juce_PushNotifications.h
modules/juce_gui_extra/misc/juce_RecentlyOpenedFilesList.cpp
modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp [new file with mode: 0644]
modules/juce_gui_extra/misc/juce_WebBrowserComponent.h
modules/juce_gui_extra/native/juce_android_PushNotifications.cpp
modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp
modules/juce_gui_extra/native/juce_ios_PushNotifications.cpp
modules/juce_gui_extra/native/juce_linux_X11_WebBrowserComponent.cpp
modules/juce_gui_extra/native/juce_linux_XEmbedComponent.cpp
modules/juce_gui_extra/native/juce_mac_AppleRemote.mm
modules/juce_gui_extra/native/juce_mac_NSViewComponent.mm
modules/juce_gui_extra/native/juce_mac_PushNotifications.cpp
modules/juce_gui_extra/native/juce_mac_WebBrowserComponent.mm
modules/juce_gui_extra/native/juce_win32_ActiveXComponent.cpp
modules/juce_gui_extra/native/juce_win32_WebBrowserComponent.cpp
modules/juce_opengl/juce_opengl.cpp
modules/juce_opengl/juce_opengl.h
modules/juce_opengl/native/juce_OpenGL_android.h
modules/juce_opengl/native/juce_OpenGL_ios.h
modules/juce_opengl/native/juce_OpenGL_linux_X11.h
modules/juce_opengl/native/juce_OpenGL_osx.h
modules/juce_opengl/native/juce_OpenGL_win32.h
modules/juce_opengl/opengl/juce_OpenGLContext.cpp
modules/juce_opengl/opengl/juce_OpenGLContext.h
modules/juce_opengl/opengl/juce_OpenGLGraphicsContext.cpp
modules/juce_osc/juce_osc.h
modules/juce_product_unlocking/in_app_purchases/juce_InAppPurchases.cpp
modules/juce_product_unlocking/in_app_purchases/juce_InAppPurchases.h
modules/juce_product_unlocking/juce_product_unlocking.h
modules/juce_product_unlocking/marketplace/juce_OnlineUnlockForm.cpp
modules/juce_product_unlocking/marketplace/juce_OnlineUnlockStatus.cpp
modules/juce_product_unlocking/marketplace/juce_OnlineUnlockStatus.h
modules/juce_product_unlocking/native/juce_android_InAppPurchases.cpp
modules/juce_video/capture/juce_CameraDevice.cpp
modules/juce_video/juce_video.h
modules/juce_video/native/juce_android_CameraDevice.h
modules/juce_video/native/juce_android_Video.h
modules/juce_video/native/juce_ios_CameraDevice.h
modules/juce_video/native/juce_mac_CameraDevice.h
modules/juce_video/native/juce_win32_CameraDevice.h
modules/juce_video/native/juce_win32_Video.h
modules/juce_video/playback/juce_VideoComponent.cpp

index 000e4d367ce2c8001918ca13723601a35da0520f..973f3e074681b16a145d26b07c27dd809bc575bc 100644 (file)
@@ -1,6 +1,232 @@
 JUCE breaking changes
 =====================
 
+Version 7.0.3
+=============
+
+Change
+------
+The default macOS and iOS deployment targets set by the Projucer have been
+increased to macOS 10.13 and iOS 11 respectively.
+
+Possible Issues
+---------------
+Projects using the Projucer's default minimum deployment target will have their
+minimum deployment target increased.
+
+Workaround
+----------
+If you need a lower minimum deployment target then you must set this in the
+Projucer's Xcode build configuration settings.
+
+Rationale
+---------
+Xcode 14 no longer supports deployment targets lower than macOS 10.13 and iOS
+11.
+
+
+Change
+------
+The ARA SDK expected by JUCE has been updated to version 2.2.0.
+
+Possible Issues
+---------------
+Builds using earlier versions of the ARA SDK will fail to compile.
+
+Workaround
+----------
+The ARA SDK configured in JUCE must be updated to version 2.2.0.
+
+Rationale
+---------
+Version 2.2.0 is the latest official release of the ARA SDK.
+
+
+Change
+------
+The Thread::startThread (int) and Thread::setPriority (int) methods have been
+removed. A new Thread priority API has been introduced.
+
+Possible Issues
+---------------
+Code will fail to compile.
+
+Workaround
+----------
+Rather than using an integer thread priority you must instead use a value from
+the Thread::Priority enum. Thread::setPriority and Thread::getPriority should
+only be called from the target thread. To start a Thread with a realtime
+performance profile you must call startRealtimeThread.
+
+Rationale
+---------
+Operating systems are moving away from a specific thread priority and towards
+more granular control over which types of cores can be used and things like
+power throttling options. In particular, it is no longer possible to map a 0-10
+integer to a meaningful performance range on macOS ARM using the pthread
+interface. Using a more modern interface grants us access to more runtime
+options, but also changes how we can work with threads. The two most
+significant changes are that we cannot mix operations using the new and old
+interfaces, and that changing a priority using the new interface can only be
+done on the currently running thread.
+
+
+Change
+------
+The constructor of WebBrowserComponent now requires passing in an instance of
+a new Options class instead of a single option boolean. The
+WindowsWebView2WebBrowserComponent class was removed.
+
+Possible Issues
+---------------
+Code using the WebBrowserComponent's boolean parameter to indicate if a
+webpage should be unloaded when the component is hidden, will now fail to
+compile. Additionally, any code using the WindowsWebView2WebBrowserComponent
+class will fail to compile. Code relying on the default value of the
+WebBrowserComponent's constructor are not affected.
+
+Workaround
+----------
+Instead of passing in a single boolean to the WebBrowserComponent's
+constructor you should now set this option via tha
+WebBrowserComponent::Options::withKeepPageLoadedWhenBrowserIsHidden method.
+
+If you were previously using WindowsWebView2WebBrowserComponent to indicate to
+JUCE that you prefer JUCE to use Windows' Webview2 browser backend, you now do
+this by setting the WebBrowserComponent::Options::withBackend method. The
+WebView2Preferences can now be modified with the methods in
+WebBrowserComponent::Options::WinWebView2.
+
+Rationale
+---------
+The old API made adding further options to the WebBrowserComponent cumbersome
+especially as the WindowsWebView2WebBrowserComponent already had a parameter
+very similar to the above Options class, whereas the base class did not use
+such a parameter. Furthermore, using an option to specify the preferred
+browser backend is more intuitive then requiring the user to derive from a
+special class, especially if additional browser backends are added in the
+future.
+
+
+Change
+------
+The function AudioIODeviceCallback::audioDeviceIOCallback() was removed.
+
+Possible Issues
+---------------
+Code overriding audioDeviceIOCallback() will fail to compile.
+
+Workaround
+----------
+Affected classes should override the audioDeviceIOCallbackWithContext() function
+instead.
+
+Rationale
+---------
+The audioDeviceIOCallbackWithContext() function fulfills the same role as
+audioDeviceIOCallback(), it just has an extra parameter. Hence the
+audioDeviceIOCallback() function was superfluous.
+
+
+Change
+------
+The type representing multi-channel audio data has been changed from T** to
+T* const*. Affected classes are AudioIODeviceCallback, AudioBuffer and
+AudioFormatReader.
+
+Possible Issues
+---------------
+Code overriding the affected AudioIODeviceCallback and AudioFormatReader
+functions will fail to compile. Code that interacts with the return value of
+AudioBuffer::getArrayOfReadPointers() and AudioBuffer::getArrayOfWritePointers()
+may fail to compile.
+
+Workaround
+----------
+Functions overriding the affected AudioIODeviceCallback and AudioFormatReader
+members will need to be changed to confirm to the new signature. Type
+declarations related to getArrayOfReadPointers() and getArrayOfWritePointers()
+of AudioBuffer may have to be adjusted.
+
+Rationale
+---------
+While the previous signature permitted it, changing the channel pointers by the
+previously used types was already being considered illegal. The earlier type
+however prevented passing T** values to parameters with type const T**. In some
+places this necessitated the usage of const_cast. The new signature can bind to
+T** values and the awkward casting can be avoided.
+
+
+Change
+------
+The minimum supported C++ standard is now C++17 and the oldest supported
+compilers on Linux are now GCC 7.0 and Clang 6.0.
+
+Possible Issues
+---------------
+Older compilers will no longer be able to compile JUCE.
+
+Workaround
+----------
+No workaround is available.
+
+Rationale
+---------
+This compiler upgrade will allow the use of C++17 within the framework.
+
+
+Change
+------
+Resource forks are no longer generated for Audio Unit plug-ins.
+
+Possible Issues
+---------------
+New builds of JUCE Audio Units may no longer load in old hosts that use the
+Component Manager to discover plug-ins.
+
+Workaround
+----------
+No workaround is available.
+
+Rationale
+---------
+The Component Manager is deprecated in macOS 10.8 and later, so the majority of
+hosts have now implemented support for the new plist-based discovery mechanism.
+The new AudioUnitSDK (https://github.com/apple/AudioUnitSDK) provided by Apple
+to replace the old Core Audio Utility Classes no longer includes the files
+required to generate resource forks.
+
+
+Change
+------
+Previously, the AudioProcessorGraph would call processBlockBypassed on any
+processor for which setBypassed had previously been called. Now, the
+AudioProcessorGraph will now only call processBlockBypassed if those processors
+do not have dedicated bypass parameters.
+
+Possible Issues
+---------------
+Processors with non-functional bypass parameters may not bypass in the same way
+as before.
+
+Workaround
+----------
+For each AudioProcessor owned by a Graph, ensure that either: the processor has
+a working bypass parameter that correctly affects the output of processBlock();
+or, the processor has no bypass parameter, in which case processBlockBypassed()
+will be called as before.
+
+Rationale
+---------
+The documentation for AudioProcessor::getBypassParameter() states that if this
+function returns non-null, then processBlockBypassed() should never be called,
+but the AudioProcessorGraph was breaking this rule. Calling
+processBlockBypassed() on AudioProcessors with bypass parameters is likely to
+result in incorrect or unexpected output if this function is not overridden.
+The new behaviour obeys the contract set out in the AudioProcessor
+documentation.
+
+
 Version 7.0.2
 =============
 
index 438e2bbca8b029e60930f0d4c20f8fcd47ae04f6..4289d0672194a580faaabcb9d594c588c8de06c6 100644 (file)
@@ -23,7 +23,7 @@
 
 cmake_minimum_required(VERSION 3.15)
 
-project(JUCE VERSION 7.0.2 LANGUAGES C CXX)
+project(JUCE VERSION 7.0.5 LANGUAGES C CXX)
 
 include(CMakeDependentOption)
 
@@ -117,10 +117,6 @@ endif()
 # ==================================================================================================
 # Install configuration
 
-if(CMAKE_VERSION VERSION_GREATER_EQUAL "3.14")
-    set(extra_version_arg ARCH_INDEPENDENT)
-endif()
-
 include(CMakePackageConfigHelpers)
 write_basic_package_version_file("${JUCE_BINARY_DIR}/JUCEConfigVersion.cmake"
     VERSION ${JUCE_VERSION}
@@ -166,4 +162,12 @@ install(FILES "${JUCE_BINARY_DIR}/JUCEConfigVersion.cmake"
               "${JUCE_CMAKE_UTILS_DIR}/juce_runtime_arch_detection.cpp"
         DESTINATION "${JUCE_INSTALL_DESTINATION}")
 
-install(EXPORT LV2_HELPER NAMESPACE juce:: DESTINATION "${JUCE_INSTALL_DESTINATION}")
+if("${CMAKE_SOURCE_DIR}" STREQUAL "${JUCE_SOURCE_DIR}")
+    _juce_add_lv2_manifest_helper_target()
+
+    if(TARGET juce_lv2_helper)
+        install(TARGETS juce_lv2_helper EXPORT LV2_HELPER DESTINATION "bin/JUCE-${JUCE_VERSION}")
+        install(EXPORT LV2_HELPER NAMESPACE juce:: DESTINATION "${JUCE_INSTALL_DESTINATION}")
+    endif()
+endif()
+
index 43cd12a5362d93727b6de0420c011ed5c2ccc309..324eebbc82837fc81325eac5e49b7b53d1d88cd9 100644 (file)
@@ -3,6 +3,27 @@
 This file just lists the more notable headline features. For more detailed info\r
 about changes and bugfixes please see the git log and BREAKING-CHANGES.txt.\r
 \r
+Version 7.0.5\r
+  - Fixed Windows 7 compatibility\r
+  - Fixed dark mode notifications on macOS\r
+  - Improved the performance of AudioProcessorGraph\r
+\r
+Version 7.0.4\r
+  - Improved Metal device handling\r
+  - Adopted more C++17 features\r
+  - Improved input handling on macOS and iOS\r
+  - Fixed a GUI display issue on Linux\r
+  - Fixed some compiler warnings\r
+\r
+Version 7.0.3\r
+  - Added a unique machine ID\r
+  - Added new threading classes\r
+  - Improved the performance of multiple OpenGL contexts\r
+  - Refactored AudioProcessorGraph\r
+  - Improved AudioDeviceManager sample rate handling\r
+  - Fixed Studio One drawing performance\r
+  - Updated the FLAC library\r
+\r
 Version 7.0.2\r
   - Fixed accessibility table navigation\r
   - Fixed Android file access on older APIs\r
index 5024834cd2aee69f613d8bb1ffa5b366f71a2211..2f675c4411e2eefbe187515a081d1169a108da2a 100644 (file)
--- a/README.md
+++ b/README.md
@@ -57,14 +57,14 @@ of the target you wish to build.
 #### Building JUCE Projects
 
 - __macOS/iOS__: Xcode 10.1 (macOS 10.13.6)
-- __Windows__: Windows 8.1 and Visual Studio 2015 Update 3 64-bit
-- __Linux__: g++ 5.0 or Clang 3.4 (for a full list of dependencies, see
+- __Windows__: Windows 8.1 and Visual Studio 2017
+- __Linux__: g++ 7.0 or Clang 6.0 (for a full list of dependencies, see
 [here](/docs/Linux%20Dependencies.md)).
 - __Android__: Android Studio on Windows, macOS or Linux
 
 #### Deployment Targets
 
-- __macOS__: macOS 10.7
+- __macOS__: macOS 10.9
 - __Windows__: Windows Vista
 - __Linux__: Mainstream Linux distributions
 - __iOS__: iOS 9.0
@@ -94,7 +94,7 @@ The JUCE framework contains the following dependencies:
 - [Oboe](modules/juce_audio_devices/native/oboe/) ([Apache 2.0](modules/juce_audio_devices/native/oboe/LICENSE))
 - [FLAC](modules/juce_audio_formats/codecs/flac/) ([BSD](modules/juce_audio_formats/codecs/flac/Flac%20Licence.txt))
 - [Ogg Vorbis](modules/juce_audio_formats/codecs/oggvorbis/) ([BSD](modules/juce_audio_formats/codecs/oggvorbis/Ogg%20Vorbis%20Licence.txt))
-- [CoreAudioUtilityClasses](modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/) ([Apple](modules/juce_audio_plugin_client/AU/CoreAudioUtilityClasses/AUBase.cpp))
+- [AudioUnitSDK](modules/juce_audio_plugin_client/AU/AudioUnitSDK/) ([Apache 2.0](modules/juce_audio_plugin_client/AU/AudioUnitSDK/LICENSE.txt))
 - [AUResources.r](modules/juce_audio_plugin_client/AUResources.r) ([Apple](modules/juce_audio_plugin_client/AUResources.r))
 - [LV2](modules/juce_audio_processors/format_types/LV2_SDK/) ([ISC](modules/juce_audio_processors/format_types/LV2_SDK/lv2/COPYING))
 - [pslextensions](modules/juce_audio_processors/format_types/pslextensions/ipslcontextinfo.h) ([Public domain](modules/juce_audio_processors/format_types/pslextensions/ipslcontextinfo.h))
index 73e961c34eaae6d3aaea785ceb02533fe1a5aea1..8eef8fbf861921e1b3cba46398f07863073b5257 100644 (file)
@@ -5,12 +5,12 @@ in JUCE there are some steps you need to take to enable all ARA related function
 
 ## External dependencies
 
-- ARA SDK 2.1.0
+- ARA SDK 2.2.0
 
 You can download the ARA SDK from Celemony's Github. The command below will recursively clone the
 right version into the `ARA_SDK` directory
 
-    git clone --recursive --branch releases/2.1.0 https://github.com/Celemony/ARA_SDK
+    git clone --recursive --branch releases/2.2.0 https://github.com/Celemony/ARA_SDK
 
 ## Enabling ARA features in JUCE
 
index e15970b4844df3245f1e273ed29da588f9175977..72e32f02b9c8a62e142a60885b05bda09fd0d0e5 100644 (file)
@@ -2,8 +2,9 @@
 
 ## What is supported?
 
-Currently JUCE supports VoiceOver on macOS and Narrator on Windows. The JUCE
-accessibility API exposes the following to these clients:
+Currently JUCE supports Narrator on Windows, VoiceOver on macOS and iOS, and
+TalkBack on Android. The JUCE accessibility API exposes the following to these
+clients:
 
   - Title, description, and help text for UI elements
   - Programmatic access to UI elements and text
index 15ec9ea48743c5c41b5571697f83fec6539a6cea..9ce59be69d0eb245d6920b38a0d6125933580115 100644 (file)
@@ -1,4 +1,4 @@
-# Doxyfile 1.8.12
+# Doxyfile 1.9.6
 
 # This file describes the settings to be used by the documentation system
 # doxygen (www.doxygen.org) for a project.
 # For lists, items can also be appended using:
 # TAG += value [value, ...]
 # Values that contain spaces should be placed between quotes (\" \").
+#
+# Note:
+#
+# Use doxygen to compare the used configuration file with the template
+# configuration file:
+# doxygen -x [configFile]
+# Use doxygen to compare the used configuration file with the template
+# configuration file without replacing the environment variables or CMake type
+# replacement variables:
+# doxygen -x_noenv [configFile]
 
 #---------------------------------------------------------------------------
 # Project related configuration options
 #---------------------------------------------------------------------------
 
-# This tag specifies the encoding used for all characters in the config file
-# that follow. The default is UTF-8 which is also the encoding used for all text
-# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
-# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
-# for the list of possible encodings.
+# This tag specifies the encoding used for all characters in the configuration
+# file that follow. The default is UTF-8 which is also the encoding used for all
+# text before the first occurrence of this tag. Doxygen uses libiconv (or the
+# iconv built into libc) for the transcoding. See
+# https://www.gnu.org/software/libiconv/ for the list of possible encodings.
 # The default value is: UTF-8.
 
 DOXYFILE_ENCODING      = UTF-8
@@ -60,16 +70,28 @@ PROJECT_LOGO           =
 
 OUTPUT_DIRECTORY       =
 
-# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
-# directories (in 2 levels) under the output directory of each output format and
-# will distribute the generated files over these directories. Enabling this
+# If the CREATE_SUBDIRS tag is set to YES then doxygen will create up to 4096
+# sub-directories (in 2 levels) under the output directory of each output format
+# and will distribute the generated files over these directories. Enabling this
 # option can be useful when feeding doxygen a huge amount of source files, where
 # putting all generated files in the same directory would otherwise causes
-# performance problems for the file system.
+# performance problems for the file system. Adapt CREATE_SUBDIRS_LEVEL to
+# control the number of sub-directories.
 # The default value is: NO.
 
 CREATE_SUBDIRS         = NO
 
+# Controls the number of sub-directories that will be created when
+# CREATE_SUBDIRS tag is set to YES. Level 0 represents 16 directories, and every
+# level increment doubles the number of directories, resulting in 4096
+# directories at level 8 which is the default and also the maximum value. The
+# sub-directories are organized in 2 levels, the first level always has a fixed
+# number of 16 directories.
+# Minimum value: 0, maximum value: 8, default value: 8.
+# This tag requires that the tag CREATE_SUBDIRS is set to YES.
+
+CREATE_SUBDIRS_LEVEL   = 8
+
 # If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
 # characters to appear in the names of generated files. If set to NO, non-ASCII
 # characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
@@ -81,14 +103,14 @@ ALLOW_UNICODE_NAMES    = NO
 # The OUTPUT_LANGUAGE tag is used to specify the language in which all
 # documentation generated by doxygen is written. Doxygen will use this
 # information to generate all constant output in the proper language.
-# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
-# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
-# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
-# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
-# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
-# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
-# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
-# Ukrainian and Vietnamese.
+# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Bulgarian,
+# Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch, English
+# (United States), Esperanto, Farsi (Persian), Finnish, French, German, Greek,
+# Hindi, Hungarian, Indonesian, Italian, Japanese, Japanese-en (Japanese with
+# English messages), Korean, Korean-en (Korean with English messages), Latvian,
+# Lithuanian, Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese,
+# Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish,
+# Swedish, Turkish, Ukrainian and Vietnamese.
 # The default value is: English.
 
 OUTPUT_LANGUAGE        = English
@@ -179,6 +201,16 @@ SHORT_NAMES            = NO
 
 JAVADOC_AUTOBRIEF      = YES
 
+# If the JAVADOC_BANNER tag is set to YES then doxygen will interpret a line
+# such as
+# /***************
+# as being the beginning of a Javadoc-style comment "banner". If set to NO, the
+# Javadoc-style will behave just like regular comments and it will not be
+# interpreted by doxygen.
+# The default value is: NO.
+
+JAVADOC_BANNER         = NO
+
 # If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
 # line (until the first dot) of a Qt-style comment as the brief description. If
 # set to NO, the Qt-style will behave just like regular Qt-style comments (thus
@@ -199,6 +231,14 @@ QT_AUTOBRIEF           = NO
 
 MULTILINE_CPP_IS_BRIEF = NO
 
+# By default Python docstrings are displayed as preformatted text and doxygen's
+# special commands cannot be used. By setting PYTHON_DOCSTRING to NO the
+# doxygen's special commands can be used and the contents of the docstring
+# documentation blocks is shown as doxygen documentation.
+# The default value is: YES.
+
+PYTHON_DOCSTRING       = YES
+
 # If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
 # documentation from any documented member that it re-implements.
 # The default value is: YES.
@@ -222,11 +262,16 @@ TAB_SIZE               = 4
 # the documentation. An alias has the form:
 # name=value
 # For example adding
-# "sideeffect=@par Side Effects:\n"
+# "sideeffect=@par Side Effects:^^"
 # will allow you to put the command \sideeffect (or @sideeffect) in the
 # documentation, which will result in a user-defined paragraph with heading
-# "Side Effects:". You can put \n's in the value part of an alias to insert
-# newlines.
+# "Side Effects:". Note that you cannot put \n's in the value part of an alias
+# to insert newlines (in the resulting output). You can put ^^ in the value part
+# of an alias to insert a newline as if a physical newline was in the original
+# file. When you need a literal { or } or , in the value part of an alias you
+# have to escape them by means of a backslash (\), this can lead to conflicts
+# with the commands \{ and \} for these it is advised to use the version @{ and
+# @} or use a double escape (\\{ and \\})
 
 ALIASES                = "tags{1}=" \
                          "topictag{1}=\1" \
@@ -251,12 +296,6 @@ ALIASES                = "tags{1}=" \
                          "c_new=@s_code{new}" \
                          "c_typedef=@s_code{typedef}"
 
-# This tag can be used to specify a number of word-keyword mappings (TCL only).
-# A mapping has the form "name=value". For example adding "class=itcl::class"
-# will allow you to use the command class in the itcl::class meaning.
-
-TCL_SUBST              =
-
 # Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
 # only. Doxygen will then generate output that is more tailored for C. For
 # instance, some of the names that are used will be different. The list of all
@@ -285,28 +324,40 @@ OPTIMIZE_FOR_FORTRAN   = NO
 
 OPTIMIZE_OUTPUT_VHDL   = NO
 
+# Set the OPTIMIZE_OUTPUT_SLICE tag to YES if your project consists of Slice
+# sources only. Doxygen will then generate output that is more tailored for that
+# language. For instance, namespaces will be presented as modules, types will be
+# separated into more groups, etc.
+# The default value is: NO.
+
+OPTIMIZE_OUTPUT_SLICE  = NO
+
 # Doxygen selects the parser to use depending on the extension of the files it
 # parses. With this tag you can assign which parser to use for a given
 # extension. Doxygen has a built-in mapping, but you can override or extend it
 # using this tag. The format is ext=language, where ext is a file extension, and
-# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
-# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
-# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
-# Fortran. In the later case the parser tries to guess whether the code is fixed
-# or free formatted code, this is the default for Fortran type files), VHDL. For
-# instance to make doxygen treat .inc files as Fortran files (default is PHP),
-# and .f files as C (default is Fortran), use: inc=Fortran f=C.
+# language is one of the parsers supported by doxygen: IDL, Java, JavaScript,
+# Csharp (C#), C, C++, Lex, D, PHP, md (Markdown), Objective-C, Python, Slice,
+# VHDL, Fortran (fixed format Fortran: FortranFixed, free formatted Fortran:
+# FortranFree, unknown formatted Fortran: Fortran. In the later case the parser
+# tries to guess whether the code is fixed or free formatted code, this is the
+# default for Fortran type files). For instance to make doxygen treat .inc files
+# as Fortran files (default is PHP), and .f files as C (default is Fortran),
+# use: inc=Fortran f=C.
 #
 # Note: For files without extension you can use no_extension as a placeholder.
 #
 # Note that for custom extensions you also need to set FILE_PATTERNS otherwise
-# the files are not read by doxygen.
+# the files are not read by doxygen. When specifying no_extension you should add
+# * to the FILE_PATTERNS.
+#
+# Note see also the list of default file extension mappings.
 
 EXTENSION_MAPPING      = txt=md
 
 # If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
 # according to the Markdown format, which allows for more readable
-# documentation. See http://daringfireball.net/projects/markdown/ for details.
+# documentation. See https://daringfireball.net/projects/markdown/ for details.
 # The output of markdown processing is further processed by doxygen, so you can
 # mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
 # case of backward compatibilities issues.
@@ -318,7 +369,7 @@ MARKDOWN_SUPPORT       = YES
 # to that level are automatically included in the table of contents, even if
 # they do not have an id attribute.
 # Note: This feature currently applies only to Markdown headings.
-# Minimum value: 0, maximum value: 99, default value: 0.
+# Minimum value: 0, maximum value: 99, default value: 5.
 # This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
 
 TOC_INCLUDE_HEADINGS   = 0
@@ -348,7 +399,7 @@ BUILTIN_STL_SUPPORT    = YES
 CPP_CLI_SUPPORT        = NO
 
 # Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
-# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
+# https://www.riverbankcomputing.com/software/sip/intro) sources only. Doxygen
 # will parse them like normal C++ but will assume all classes use public instead
 # of private inheritance when no explicit protection keyword is present.
 # The default value is: NO.
@@ -434,6 +485,19 @@ TYPEDEF_HIDES_STRUCT   = NO
 
 LOOKUP_CACHE_SIZE      = 0
 
+# The NUM_PROC_THREADS specifies the number of threads doxygen is allowed to use
+# during processing. When set to 0 doxygen will based this on the number of
+# cores available in the system. You can set it explicitly to a value larger
+# than 0 to get more control over the balance between CPU load and processing
+# speed. At this moment only the input processing can be done using multiple
+# threads. Since this is still an experimental feature the default is set to 1,
+# which effectively disables parallel processing. Please report any issues you
+# encounter. Generating dot graphs in parallel is controlled by the
+# DOT_NUM_THREADS setting.
+# Minimum value: 0, maximum value: 32, default value: 1.
+
+NUM_PROC_THREADS       = 1
+
 #---------------------------------------------------------------------------
 # Build related configuration options
 #---------------------------------------------------------------------------
@@ -454,6 +518,12 @@ EXTRACT_ALL            = YES
 
 EXTRACT_PRIVATE        = NO
 
+# If the EXTRACT_PRIV_VIRTUAL tag is set to YES, documented private virtual
+# methods of a class will be included in the documentation.
+# The default value is: NO.
+
+EXTRACT_PRIV_VIRTUAL   = NO
+
 # If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
 # scope will be included in the documentation.
 # The default value is: NO.
@@ -491,6 +561,13 @@ EXTRACT_LOCAL_METHODS  = NO
 
 EXTRACT_ANON_NSPACES   = NO
 
+# If this flag is set to YES, the name of an unnamed parameter in a declaration
+# will be determined by the corresponding definition. By default unnamed
+# parameters remain unnamed in the output.
+# The default value is: YES.
+
+RESOLVE_UNNAMED_PARAMS = YES
+
 # If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
 # undocumented members inside documented classes or files. If set to NO these
 # members will be included in the various overviews, but no documentation
@@ -502,14 +579,15 @@ HIDE_UNDOC_MEMBERS     = NO
 # If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
 # undocumented classes that are normally visible in the class hierarchy. If set
 # to NO, these classes will be included in the various overviews. This option
-# has no effect if EXTRACT_ALL is enabled.
+# will also hide undocumented C++ concepts if enabled. This option has no effect
+# if EXTRACT_ALL is enabled.
 # The default value is: NO.
 
 HIDE_UNDOC_CLASSES     = YES
 
 # If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
-# (class|struct|union) declarations. If set to NO, these declarations will be
-# included in the documentation.
+# declarations. If set to NO, these declarations will be included in the
+# documentation.
 # The default value is: NO.
 
 HIDE_FRIEND_COMPOUNDS  = YES
@@ -528,12 +606,20 @@ HIDE_IN_BODY_DOCS      = YES
 
 INTERNAL_DOCS          = YES
 
-# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
-# names in lower-case letters. If set to YES, upper-case letters are also
-# allowed. This is useful if you have classes or files whose names only differ
-# in case and if your file system supports case sensitive file names. Windows
-# and Mac users are advised to set this option to NO.
-# The default value is: system dependent.
+# With the correct setting of option CASE_SENSE_NAMES doxygen will better be
+# able to match the capabilities of the underlying filesystem. In case the
+# filesystem is case sensitive (i.e. it supports files in the same directory
+# whose names only differ in casing), the option must be set to YES to properly
+# deal with such files in case they appear in the input. For filesystems that
+# are not case sensitive the option should be set to NO to properly deal with
+# output files written for symbols that only differ in casing, such as for two
+# classes, one named CLASS and the other named Class, and to also support
+# references to files without having to specify the exact matching casing. On
+# Windows (including Cygwin) and MacOS, users should typically set this option
+# to NO, whereas on Linux or other Unix flavors it should typically be set to
+# YES.
+# Possible values are: SYSTEM, NO and YES.
+# The default value is: SYSTEM.
 
 CASE_SENSE_NAMES       = YES
 
@@ -551,6 +637,12 @@ HIDE_SCOPE_NAMES       = NO
 
 HIDE_COMPOUND_REFERENCE= NO
 
+# If the SHOW_HEADERFILE tag is set to YES then the documentation for a class
+# will show which file needs to be included to use the class.
+# The default value is: YES.
+
+SHOW_HEADERFILE        = YES
+
 # If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
 # the files that are included by a file in the documentation of that file.
 # The default value is: YES.
@@ -708,7 +800,8 @@ FILE_VERSION_FILTER    =
 # output files in an output format independent way. To create the layout file
 # that represents doxygen's defaults, run doxygen with the -l option. You can
 # optionally specify a file name after the option, if omitted DoxygenLayout.xml
-# will be used as the name of the layout file.
+# will be used as the name of the layout file. See also section "Changing the
+# layout of pages" for information.
 #
 # Note that if you run doxygen from a directory containing a file called
 # DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
@@ -719,7 +812,7 @@ LAYOUT_FILE            =
 # The CITE_BIB_FILES tag can be used to specify one or more bib files containing
 # the reference definitions. This must be a list of .bib files. The .bib
 # extension is automatically appended if omitted. This requires the bibtex tool
-# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
+# to be installed. See also https://en.wikipedia.org/wiki/BibTeX for more info.
 # For LaTeX the style of the bibliography can be controlled using
 # LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
 # search path. See also \cite for info how to create references.
@@ -754,23 +847,43 @@ WARNINGS               = YES
 WARN_IF_UNDOCUMENTED   = YES
 
 # If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
-# potential errors in the documentation, such as not documenting some parameters
-# in a documented function, or documenting parameters that don't exist or using
-# markup commands wrongly.
+# potential errors in the documentation, such as documenting some parameters in
+# a documented function twice, or documenting parameters that don't exist or
+# using markup commands wrongly.
 # The default value is: YES.
 
 WARN_IF_DOC_ERROR      = YES
 
+# If WARN_IF_INCOMPLETE_DOC is set to YES, doxygen will warn about incomplete
+# function parameter documentation. If set to NO, doxygen will accept that some
+# parameters have no documentation without warning.
+# The default value is: YES.
+
+WARN_IF_INCOMPLETE_DOC = YES
+
 # This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
 # are documented, but have no documentation for their parameters or return
-# value. If set to NO, doxygen will only warn about wrong or incomplete
-# parameter documentation, but not about the absence of documentation.
+# value. If set to NO, doxygen will only warn about wrong parameter
+# documentation, but not about the absence of documentation. If EXTRACT_ALL is
+# set to YES then this flag will automatically be disabled. See also
+# WARN_IF_INCOMPLETE_DOC
 # The default value is: NO.
 
 WARN_NO_PARAMDOC       = NO
 
+# If WARN_IF_UNDOC_ENUM_VAL option is set to YES, doxygen will warn about
+# undocumented enumeration values. If set to NO, doxygen will accept
+# undocumented enumeration values. If EXTRACT_ALL is set to YES then this flag
+# will automatically be disabled.
+# The default value is: NO.
+
+WARN_IF_UNDOC_ENUM_VAL = NO
+
 # If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
-# a warning is encountered.
+# a warning is encountered. If the WARN_AS_ERROR tag is set to FAIL_ON_WARNINGS
+# then doxygen will continue running as if WARN_AS_ERROR tag is set to NO, but
+# at the end of the doxygen process doxygen will return with a non-zero status.
+# Possible values are: NO, YES and FAIL_ON_WARNINGS.
 # The default value is: NO.
 
 WARN_AS_ERROR          = NO
@@ -781,13 +894,27 @@ WARN_AS_ERROR          = NO
 # and the warning text. Optionally the format may contain $version, which will
 # be replaced by the version of the file (if it could be obtained via
 # FILE_VERSION_FILTER)
+# See also: WARN_LINE_FORMAT
 # The default value is: $file:$line: $text.
 
 WARN_FORMAT            = "$file:$line: $text"
 
+# In the $text part of the WARN_FORMAT command it is possible that a reference
+# to a more specific place is given. To make it easier to jump to this place
+# (outside of doxygen) the user can define a custom "cut" / "paste" string.
+# Example:
+# WARN_LINE_FORMAT = "'vi $file +$line'"
+# See also: WARN_FORMAT
+# The default value is: at line $line of file $file.
+
+WARN_LINE_FORMAT       = "at line $line of file $file"
+
 # The WARN_LOGFILE tag can be used to specify a file to which warning and error
 # messages should be written. If left blank the output is written to standard
-# error (stderr).
+# error (stderr). In case the file specified cannot be opened for writing the
+# warning and error messages are written to standard error. When as file - is
+# specified the warning and error messages are written to standard output
+# (stdout).
 
 WARN_LOGFILE           =
 
@@ -808,12 +935,23 @@ INPUT                  = build \
 # This tag can be used to specify the character encoding of the source files
 # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
 # libiconv (or the iconv built into libc) for the transcoding. See the libiconv
-# documentation (see: http://www.gnu.org/software/libiconv) for the list of
-# possible encodings.
+# documentation (see:
+# https://www.gnu.org/software/libiconv/) for the list of possible encodings.
+# See also: INPUT_FILE_ENCODING
 # The default value is: UTF-8.
 
 INPUT_ENCODING         = UTF-8
 
+# This tag can be used to specify the character encoding of the source files
+# that doxygen parses The INPUT_FILE_ENCODING tag can be used to specify
+# character encoding on a per file pattern basis. Doxygen will compare the file
+# name with each pattern and apply the encoding instead of the default
+# INPUT_ENCODING) if there is a match. The character encodings are a list of the
+# form: pattern=encoding (like *.php=ISO-8859-1). See cfg_input_encoding
+# "INPUT_ENCODING" for further information on supported encodings.
+
+INPUT_FILE_ENCODING    =
+
 # If the value of the INPUT tag contains directories, you can use the
 # FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
 # *.h) to filter out the source-files in the directories.
@@ -822,11 +960,15 @@ INPUT_ENCODING         = UTF-8
 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
 # read by doxygen.
 #
+# Note the list of default checked file patterns might differ from the list of
+# default file extension mappings.
+#
 # If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
 # *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
-# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
-# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
-# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
+# *.hh, *.hxx, *.hpp, *.h++, *.l, *.cs, *.d, *.php, *.php4, *.php5, *.phtml,
+# *.inc, *.m, *.markdown, *.md, *.mm, *.dox (to be provided as doxygen C
+# comment), *.py, *.pyw, *.f90, *.f95, *.f03, *.f08, *.f18, *.f, *.for, *.vhd,
+# *.vhdl, *.ucf, *.qsf and *.ice.
 
 FILE_PATTERNS          = juce_*.h \
                          juce_*.dox
@@ -849,7 +991,7 @@ EXCLUDE                = build/juce_graphics/image_formats \
                          build/juce_audio_formats/codecs/flac \
                          build/juce_audio_formats/codecs/oggvorbis \
                          build/juce_audio_devices/native \
-                         build/juce_audio_plugin_client/AU/CoreAudioUtilityClasses \
+                         build/juce_audio_plugin_client/AU/AudioUnitSDK \
                          build/juce_browser_plugin_client/juce_browser_plugin.h \
                          build/juce_core/native \
                          build/juce_events/native \
@@ -883,7 +1025,7 @@ EXCLUDE_PATTERNS       = juce_GIFLoader* \
 # (namespaces, classes, functions, etc.) that should be excluded from the
 # output. The symbol name can be a fully qualified name, a word, or if the
 # wildcard * is used, a substring. Examples: ANamespace, AClass,
-# AClass::ANamespace, ANamespace::*Test
+# ANamespace::AClass, ANamespace::*Test
 #
 # Note that the wildcards are matched against the file with absolute path, so to
 # exclude all test directories use the pattern */test/*
@@ -931,6 +1073,11 @@ IMAGE_PATH             =
 # code is scanned, but not when the output code is generated. If lines are added
 # or removed, the anchors will not be placed correctly.
 #
+# Note that doxygen will use the data processed and written to standard output
+# for further processing, therefore nothing else, like debug statements or used
+# commands (so in case of a Windows batch file always use @echo OFF), should be
+# written to standard output.
+#
 # Note that for custom extensions or not directly supported extensions you also
 # need to set EXTENSION_MAPPING for the extension otherwise the files are not
 # properly processed by doxygen.
@@ -972,6 +1119,15 @@ FILTER_SOURCE_PATTERNS =
 
 USE_MDFILE_AS_MAINPAGE =
 
+# The Fortran standard specifies that for fixed formatted Fortran code all
+# characters from position 72 are to be considered as comment. A common
+# extension is to allow longer lines before the automatic comment starts. The
+# setting FORTRAN_COMMENT_AFTER will also make it possible that longer lines can
+# be processed before the automatic comment starts.
+# Minimum value: 7, maximum value: 10000, default value: 72.
+
+FORTRAN_COMMENT_AFTER  = 72
+
 #---------------------------------------------------------------------------
 # Configuration options related to source browsing
 #---------------------------------------------------------------------------
@@ -999,7 +1155,7 @@ INLINE_SOURCES         = NO
 STRIP_CODE_COMMENTS    = YES
 
 # If the REFERENCED_BY_RELATION tag is set to YES then for each documented
-# function all documented functions referencing it will be listed.
+# entity all documented functions referencing it will be listed.
 # The default value is: NO.
 
 REFERENCED_BY_RELATION = YES
@@ -1031,12 +1187,12 @@ SOURCE_TOOLTIPS        = YES
 # If the USE_HTAGS tag is set to YES then the references to source code will
 # point to the HTML generated by the htags(1) tool instead of doxygen built-in
 # source browser. The htags tool is part of GNU's global source tagging system
-# (see http://www.gnu.org/software/global/global.html). You will need version
+# (see https://www.gnu.org/software/global/global.html). You will need version
 # 4.8.6 or higher.
 #
 # To use it do the following:
 # - Install the latest version of global
-# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
+# - Enable SOURCE_BROWSER and USE_HTAGS in the configuration file
 # - Make sure the INPUT points to the root of the source tree
 # - Run doxygen as normal
 #
@@ -1069,17 +1225,11 @@ VERBATIM_HEADERS       = NO
 
 ALPHABETICAL_INDEX     = YES
 
-# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
-# which the alphabetical index list will be split.
-# Minimum value: 1, maximum value: 20, default value: 5.
-# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
-
-COLS_IN_ALPHA_INDEX    = 3
-
-# In case all classes in a project start with a common prefix, all classes will
-# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
-# can be used to specify a prefix (or a list of prefixes) that should be ignored
-# while generating the index headers.
+# The IGNORE_PREFIX tag can be used to specify a prefix (or a list of prefixes)
+# that should be ignored while generating the index headers. The IGNORE_PREFIX
+# tag works for classes, function and member names. The entity will be placed in
+# the alphabetical list under the first letter of the entity name that remains
+# after removing the prefix.
 # This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
 
 IGNORE_PREFIX          =
@@ -1158,7 +1308,12 @@ HTML_STYLESHEET        =
 # Doxygen will copy the style sheet files to the output directory.
 # Note: The order of the extra style sheet files is of importance (e.g. the last
 # style sheet in the list overrules the setting of the previous ones in the
-# list). For an example see the documentation.
+# list).
+# Note: Since the styling of scrollbars can currently not be overruled in
+# Webkit/Chromium, the styling will be left out of the default doxygen.css if
+# one or more extra stylesheets have been specified. So if scrollbar
+# customization is desired it has to be added explicitly. For an example see the
+# documentation.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
 HTML_EXTRA_STYLESHEET  =
@@ -1173,10 +1328,23 @@ HTML_EXTRA_STYLESHEET  =
 
 HTML_EXTRA_FILES       =
 
+# The HTML_COLORSTYLE tag can be used to specify if the generated HTML output
+# should be rendered with a dark or light theme.
+# Possible values are: LIGHT always generate light mode output, DARK always
+# generate dark mode output, AUTO_LIGHT automatically set the mode according to
+# the user preference, use light mode if no preference is set (the default),
+# AUTO_DARK automatically set the mode according to the user preference, use
+# dark mode if no preference is set and TOGGLE allow to user to switch between
+# light and dark mode via a button.
+# The default value is: AUTO_LIGHT.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_COLORSTYLE        = AUTO_LIGHT
+
 # The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
 # will adjust the colors in the style sheet and background images according to
-# this color. Hue is specified as an angle on a colorwheel, see
-# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
+# this color. Hue is specified as an angle on a color-wheel, see
+# https://en.wikipedia.org/wiki/Hue for more information. For instance the value
 # 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
 # purple, and 360 is red again.
 # Minimum value: 0, maximum value: 359, default value: 220.
@@ -1185,7 +1353,7 @@ HTML_EXTRA_FILES       =
 HTML_COLORSTYLE_HUE    = 220
 
 # The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
-# in the HTML output. For a value of 0 the output will use grayscales only. A
+# in the HTML output. For a value of 0 the output will use gray-scales only. A
 # value of 255 will produce the most vivid colors.
 # Minimum value: 0, maximum value: 255, default value: 100.
 # This tag requires that the tag GENERATE_HTML is set to YES.
@@ -1212,6 +1380,17 @@ HTML_COLORSTYLE_GAMMA  = 80
 
 HTML_TIMESTAMP         = YES
 
+# If the HTML_DYNAMIC_MENUS tag is set to YES then the generated HTML
+# documentation will contain a main index with vertical navigation menus that
+# are dynamically created via JavaScript. If disabled, the navigation index will
+# consists of multiple levels of tabs that are statically embedded in every HTML
+# page. Disable this option to support browsers that do not have JavaScript,
+# like the Qt help browser.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_DYNAMIC_MENUS     = NO
+
 # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
 # documentation will contain sections that can be hidden and shown after the
 # page has loaded.
@@ -1235,13 +1414,14 @@ HTML_INDEX_NUM_ENTRIES = 32
 
 # If the GENERATE_DOCSET tag is set to YES, additional index files will be
 # generated that can be used as input for Apple's Xcode 3 integrated development
-# environment (see: http://developer.apple.com/tools/xcode/), introduced with
-# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
-# Makefile in the HTML output directory. Running make will produce the docset in
-# that directory and running make install will install the docset in
+# environment (see:
+# https://developer.apple.com/xcode/), introduced with OSX 10.5 (Leopard). To
+# create a documentation set, doxygen will generate a Makefile in the HTML
+# output directory. Running make will produce the docset in that directory and
+# running make install will install the docset in
 # ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
-# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
-# for more information.
+# startup. See https://developer.apple.com/library/archive/featuredarticles/Doxy
+# genXcode/_index.html for more information.
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
@@ -1255,6 +1435,13 @@ GENERATE_DOCSET        = NO
 
 DOCSET_FEEDNAME        = "Doxygen generated docs"
 
+# This tag determines the URL of the docset feed. A documentation feed provides
+# an umbrella under which multiple documentation sets from a single provider
+# (such as a company or product suite) can be grouped.
+# This tag requires that the tag GENERATE_DOCSET is set to YES.
+
+DOCSET_FEEDURL         =
+
 # This tag specifies a string that should uniquely identify the documentation
 # set bundle. This should be a reverse domain-name style string, e.g.
 # com.mycompany.MyDocSet. Doxygen will append .docset to the name.
@@ -1280,8 +1467,12 @@ DOCSET_PUBLISHER_NAME  = Publisher
 # If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
 # additional HTML index files: index.hhp, index.hhc, and index.hhk. The
 # index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
-# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
-# Windows.
+# on Windows. In the beginning of 2021 Microsoft took the original page, with
+# a.o. the download links, offline the HTML help workshop was already many years
+# in maintenance mode). You can download the HTML help workshop from the web
+# archives at Installation executable (see:
+# http://web.archive.org/web/20160201063255/http://download.microsoft.com/downlo
+# ad/0/A/9/0A939EF6-E31C-430F-A3DF-DFAE7960D564/htmlhelp.exe).
 #
 # The HTML Help Workshop contains a compiler that can convert all HTML output
 # generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
@@ -1311,7 +1502,7 @@ CHM_FILE               =
 HHC_LOCATION           =
 
 # The GENERATE_CHI flag controls if a separate .chi index file is generated
-# (YES) or that it should be included in the master .chm file (NO).
+# (YES) or that it should be included in the main .chm file (NO).
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTMLHELP is set to YES.
 
@@ -1356,7 +1547,8 @@ QCH_FILE               =
 
 # The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
 # Project output. For more information please see Qt Help Project / Namespace
-# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
+# (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#namespace).
 # The default value is: org.doxygen.Project.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
@@ -1364,8 +1556,8 @@ QHP_NAMESPACE          = org.doxygen.Project
 
 # The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
 # Help Project output. For more information please see Qt Help Project / Virtual
-# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
-# folders).
+# Folders (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#virtual-folders).
 # The default value is: doc.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
@@ -1373,30 +1565,30 @@ QHP_VIRTUAL_FOLDER     = doc
 
 # If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
 # filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_CUST_FILTER_NAME   =
 
 # The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
 # custom filter to add. For more information please see Qt Help Project / Custom
-# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
-# filters).
+# Filters (see:
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#custom-filters).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_CUST_FILTER_ATTRS  =
 
 # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
 # project's filter section matches. Qt Help Project / Filter Attributes (see:
-# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
+# https://doc.qt.io/archives/qt-4.8/qthelpproject.html#filter-attributes).
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHP_SECT_FILTER_ATTRS  =
 
-# The QHG_LOCATION tag can be used to specify the location of Qt's
-# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
-# generated .qhp file.
+# The QHG_LOCATION tag can be used to specify the location (absolute path
+# including file name) of Qt's qhelpgenerator. If non-empty doxygen will try to
+# run qhelpgenerator on the generated .qhp file.
 # This tag requires that the tag GENERATE_QHP is set to YES.
 
 QHG_LOCATION           =
@@ -1439,16 +1631,28 @@ DISABLE_INDEX          = NO
 # to work a browser that supports JavaScript, DHTML, CSS and frames is required
 # (i.e. any modern browser). Windows users are probably better off using the
 # HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
-# further fine-tune the look of the index. As an example, the default style
-# sheet generated by doxygen has an example that shows how to put an image at
-# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
-# the same information as the tab index, you could consider setting
-# DISABLE_INDEX to YES when enabling this option.
+# further fine tune the look of the index (see "Fine-tuning the output"). As an
+# example, the default style sheet generated by doxygen has an example that
+# shows how to put an image at the root of the tree instead of the PROJECT_NAME.
+# Since the tree basically has the same information as the tab index, you could
+# consider setting DISABLE_INDEX to YES when enabling this option.
 # The default value is: NO.
 # This tag requires that the tag GENERATE_HTML is set to YES.
 
 GENERATE_TREEVIEW      = NO
 
+# When both GENERATE_TREEVIEW and DISABLE_INDEX are set to YES, then the
+# FULL_SIDEBAR option determines if the side bar is limited to only the treeview
+# area (value NO) or if it should extend to the full height of the window (value
+# YES). Setting this to YES gives a layout similar to
+# https://docs.readthedocs.io with more room for contents, but less room for the
+# project logo, title, and description. If either GENERATE_TREEVIEW or
+# DISABLE_INDEX is set to NO, this option has no effect.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+FULL_SIDEBAR           = NO
+
 # The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
 # doxygen will group on one line in the generated HTML documentation.
 #
@@ -1473,6 +1677,24 @@ TREEVIEW_WIDTH         = 320
 
 EXT_LINKS_IN_WINDOW    = NO
 
+# If the OBFUSCATE_EMAILS tag is set to YES, doxygen will obfuscate email
+# addresses.
+# The default value is: YES.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+OBFUSCATE_EMAILS       = YES
+
+# If the HTML_FORMULA_FORMAT option is set to svg, doxygen will use the pdf2svg
+# tool (see https://github.com/dawbarton/pdf2svg) or inkscape (see
+# https://inkscape.org) to generate formulas as SVG images instead of PNGs for
+# the HTML output. These images will generally look nicer at scaled resolutions.
+# Possible values are: png (the default) and svg (looks nicer but requires the
+# pdf2svg or inkscape tool).
+# The default value is: png.
+# This tag requires that the tag GENERATE_HTML is set to YES.
+
+HTML_FORMULA_FORMAT    = png
+
 # Use this tag to change the font size of LaTeX formulas included as images in
 # the HTML documentation. When you change the font size after a successful
 # doxygen run you need to manually remove any form_*.png images from the HTML
@@ -1482,19 +1704,14 @@ EXT_LINKS_IN_WINDOW    = NO
 
 FORMULA_FONTSIZE       = 10
 
-# Use the FORMULA_TRANPARENT tag to determine whether or not the images
-# generated for formulas are transparent PNGs. Transparent PNGs are not
-# supported properly for IE 6.0, but are supported on all modern browsers.
-#
-# Note that when changing this option you need to delete any form_*.png files in
-# the HTML output directory before the changes have effect.
-# The default value is: YES.
-# This tag requires that the tag GENERATE_HTML is set to YES.
+# The FORMULA_MACROFILE can contain LaTeX \newcommand and \renewcommand commands
+# to create new LaTeX commands to be used in formulas as building blocks. See
+# the section "Including formulas" for details.
 
-FORMULA_TRANSPARENT    = YES
+FORMULA_MACROFILE      =
 
 # Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
-# http://www.mathjax.org) which uses client side Javascript for the rendering
+# https://www.mathjax.org) which uses client side JavaScript for the rendering
 # instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
 # installed or if you want to formulas look prettier in the HTML output. When
 # enabled you may also need to install MathJax separately and configure the path
@@ -1504,11 +1721,29 @@ FORMULA_TRANSPARENT    = YES
 
 USE_MATHJAX            = NO
 
+# With MATHJAX_VERSION it is possible to specify the MathJax version to be used.
+# Note that the different versions of MathJax have different requirements with
+# regards to the different settings, so it is possible that also other MathJax
+# settings have to be changed when switching between the different MathJax
+# versions.
+# Possible values are: MathJax_2 and MathJax_3.
+# The default value is: MathJax_2.
+# This tag requires that the tag USE_MATHJAX is set to YES.
+
+MATHJAX_VERSION        = MathJax_2
+
 # When MathJax is enabled you can set the default output format to be used for
-# the MathJax output. See the MathJax site (see:
-# http://docs.mathjax.org/en/latest/output.html) for more details.
+# the MathJax output. For more details about the output format see MathJax
+# version 2 (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) and MathJax version 3
+# (see:
+# http://docs.mathjax.org/en/latest/web/components/output.html).
 # Possible values are: HTML-CSS (which is slower, but has the best
-# compatibility), NativeMML (i.e. MathML) and SVG.
+# compatibility. This is the name for Mathjax version 2, for MathJax version 3
+# this will be translated into chtml), NativeMML (i.e. MathML. Only supported
+# for NathJax 2. For MathJax version 3 chtml will be used instead.), chtml (This
+# is the name for Mathjax version 3, for MathJax version 2 this will be
+# translated into HTML-CSS) and SVG.
 # The default value is: HTML-CSS.
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
@@ -1521,22 +1756,29 @@ MATHJAX_FORMAT         = HTML-CSS
 # MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
 # Content Delivery Network so you can quickly see the result without installing
 # MathJax. However, it is strongly recommended to install a local copy of
-# MathJax from http://www.mathjax.org before deployment.
-# The default value is: http://cdn.mathjax.org/mathjax/latest.
+# MathJax from https://www.mathjax.org before deployment. The default value is:
+# - in case of MathJax version 2: https://cdn.jsdelivr.net/npm/mathjax@2
+# - in case of MathJax version 3: https://cdn.jsdelivr.net/npm/mathjax@3
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_RELPATH        = http://www.mathjax.org/mathjax
 
 # The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
 # extension names that should be enabled during MathJax rendering. For example
+# for MathJax version 2 (see
+# https://docs.mathjax.org/en/v2.7-latest/tex.html#tex-and-latex-extensions):
 # MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
+# For example for MathJax version 3 (see
+# http://docs.mathjax.org/en/latest/input/tex/extensions/index.html):
+# MATHJAX_EXTENSIONS = ams
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
 MATHJAX_EXTENSIONS     =
 
 # The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
 # of code that will be used on startup of the MathJax code. See the MathJax site
-# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
+# (see:
+# http://docs.mathjax.org/en/v2.7-latest/output.html) for more details. For an
 # example see the documentation.
 # This tag requires that the tag USE_MATHJAX is set to YES.
 
@@ -1564,7 +1806,7 @@ MATHJAX_CODEFILE       =
 SEARCHENGINE           = YES
 
 # When the SERVER_BASED_SEARCH tag is enabled the search engine will be
-# implemented using a web server instead of a web client using Javascript. There
+# implemented using a web server instead of a web client using JavaScript. There
 # are two flavors of web server based searching depending on the EXTERNAL_SEARCH
 # setting. When disabled, doxygen will generate a PHP script for searching and
 # an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
@@ -1583,7 +1825,8 @@ SERVER_BASED_SEARCH    = NO
 #
 # Doxygen ships with an example indexer (doxyindexer) and search engine
 # (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/).
+# Xapian (see:
+# https://xapian.org/).
 #
 # See the section "External Indexing and Searching" for details.
 # The default value is: NO.
@@ -1596,8 +1839,9 @@ EXTERNAL_SEARCH        = NO
 #
 # Doxygen ships with an example indexer (doxyindexer) and search engine
 # (doxysearch.cgi) which are based on the open source search engine library
-# Xapian (see: http://xapian.org/). See the section "External Indexing and
-# Searching" for details.
+# Xapian (see:
+# https://xapian.org/). See the section "External Indexing and Searching" for
+# details.
 # This tag requires that the tag SEARCHENGINE is set to YES.
 
 SEARCHENGINE_URL       =
@@ -1648,21 +1892,35 @@ LATEX_OUTPUT           = latex
 # The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
 # invoked.
 #
-# Note that when enabling USE_PDFLATEX this option is only used for generating
-# bitmaps for formulas in the HTML output, but not in the Makefile that is
-# written to the output directory.
-# The default file is: latex.
+# Note that when not enabling USE_PDFLATEX the default is latex when enabling
+# USE_PDFLATEX the default is pdflatex and when in the later case latex is
+# chosen this is overwritten by pdflatex. For specific output languages the
+# default can have been set differently, this depends on the implementation of
+# the output language.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_CMD_NAME         = latex
 
 # The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
 # index for LaTeX.
+# Note: This tag is used in the Makefile / make.bat.
+# See also: LATEX_MAKEINDEX_CMD for the part in the generated output file
+# (.tex).
 # The default file is: makeindex.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 MAKEINDEX_CMD_NAME     = makeindex
 
+# The LATEX_MAKEINDEX_CMD tag can be used to specify the command name to
+# generate index for LaTeX. In case there is no backslash (\) as first character
+# it will be automatically added in the LaTeX code.
+# Note: This tag is used in the generated output file (.tex).
+# See also: MAKEINDEX_CMD_NAME for the part in the Makefile / make.bat.
+# The default value is: makeindex.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_MAKEINDEX_CMD    = makeindex
+
 # If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
 # documents. This may be useful for small projects and may help to save some
 # trees in general.
@@ -1678,7 +1936,7 @@ COMPACT_LATEX          = NO
 # The default value is: a4.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
-PAPER_TYPE             = a4wide
+PAPER_TYPE             = a4
 
 # The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
 # that should be included in the LaTeX output. The package can be specified just
@@ -1692,29 +1950,31 @@ PAPER_TYPE             = a4wide
 
 EXTRA_PACKAGES         =
 
-# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
-# generated LaTeX document. The header should contain everything until the first
-# chapter. If it is left blank doxygen will generate a standard header. See
-# section "Doxygen usage" for information on how to let doxygen write the
-# default header to a separate file.
+# The LATEX_HEADER tag can be used to specify a user-defined LaTeX header for
+# the generated LaTeX document. The header should contain everything until the
+# first chapter. If it is left blank doxygen will generate a standard header. It
+# is highly recommended to start with a default header using
+# doxygen -w latex new_header.tex new_footer.tex new_stylesheet.sty
+# and then modify the file new_header.tex. See also section "Doxygen usage" for
+# information on how to generate the default header that doxygen normally uses.
 #
-# Note: Only use a user-defined header if you know what you are doing! The
-# following commands have a special meaning inside the header: $title,
-# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
-# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
-# string, for the replacement values of the other commands the user is referred
-# to HTML_HEADER.
+# Note: Only use a user-defined header if you know what you are doing!
+# Note: The header is subject to change so you typically have to regenerate the
+# default header when upgrading to a newer version of doxygen. The following
+# commands have a special meaning inside the header (and footer): For a
+# description of the possible markers and block names see the documentation.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_HEADER           =
 
-# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
-# generated LaTeX document. The footer should contain everything after the last
-# chapter. If it is left blank doxygen will generate a standard footer. See
+# The LATEX_FOOTER tag can be used to specify a user-defined LaTeX footer for
+# the generated LaTeX document. The footer should contain everything after the
+# last chapter. If it is left blank doxygen will generate a standard footer. See
 # LATEX_HEADER for more information on how to generate a default footer and what
-# special commands can be used inside the footer.
-#
-# Note: Only use a user-defined footer if you know what you are doing!
+# special commands can be used inside the footer. See also section "Doxygen
+# usage" for information on how to generate the default footer that doxygen
+# normally uses. Note: Only use a user-defined footer if you know what you are
+# doing!
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
 LATEX_FOOTER           =
@@ -1747,9 +2007,11 @@ LATEX_EXTRA_FILES      =
 
 PDF_HYPERLINKS         = NO
 
-# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
-# the PDF file directly from the LaTeX files. Set this option to YES, to get a
-# higher quality PDF documentation.
+# If the USE_PDFLATEX tag is set to YES, doxygen will use the engine as
+# specified with LATEX_CMD_NAME to generate the PDF file directly from the LaTeX
+# files. Set this option to YES, to get a higher quality PDF documentation.
+#
+# See also section LATEX_CMD_NAME for selecting the engine.
 # The default value is: YES.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
@@ -1757,8 +2019,7 @@ USE_PDFLATEX           = NO
 
 # If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
 # command to the generated LaTeX files. This will instruct LaTeX to keep running
-# if errors occur, instead of asking the user for help. This option is also used
-# when generating formulas in HTML.
+# if errors occur, instead of asking the user for help.
 # The default value is: NO.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
@@ -1771,19 +2032,9 @@ LATEX_BATCHMODE        = NO
 
 LATEX_HIDE_INDICES     = NO
 
-# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
-# code with syntax highlighting in the LaTeX output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_LATEX is set to YES.
-
-LATEX_SOURCE_CODE      = NO
-
 # The LATEX_BIB_STYLE tag can be used to specify the style to use for the
 # bibliography, e.g. plainnat, or ieeetr. See
-# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
+# https://en.wikipedia.org/wiki/BibTeX and \cite for more info.
 # The default value is: plain.
 # This tag requires that the tag GENERATE_LATEX is set to YES.
 
@@ -1797,6 +2048,14 @@ LATEX_BIB_STYLE        = plain
 
 LATEX_TIMESTAMP        = NO
 
+# The LATEX_EMOJI_DIRECTORY tag is used to specify the (relative or absolute)
+# path from which the emoji images will be read. If a relative path is entered,
+# it will be relative to the LATEX_OUTPUT directory. If left blank the
+# LATEX_OUTPUT directory will be used.
+# This tag requires that the tag GENERATE_LATEX is set to YES.
+
+LATEX_EMOJI_DIRECTORY  =
+
 #---------------------------------------------------------------------------
 # Configuration options related to the RTF output
 #---------------------------------------------------------------------------
@@ -1836,9 +2095,9 @@ COMPACT_RTF            = NO
 
 RTF_HYPERLINKS         = NO
 
-# Load stylesheet definitions from file. Syntax is similar to doxygen's config
-# file, i.e. a series of assignments. You only have to provide replacements,
-# missing definitions are set to their default value.
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# configuration file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
 #
 # See also section "Doxygen usage" for information on how to generate the
 # default style sheet that doxygen normally uses.
@@ -1847,22 +2106,12 @@ RTF_HYPERLINKS         = NO
 RTF_STYLESHEET_FILE    =
 
 # Set optional variables used in the generation of an RTF document. Syntax is
-# similar to doxygen's config file. A template extensions file can be generated
-# using doxygen -e rtf extensionFile.
+# similar to doxygen's configuration file. A template extensions file can be
+# generated using doxygen -e rtf extensionFile.
 # This tag requires that the tag GENERATE_RTF is set to YES.
 
 RTF_EXTENSIONS_FILE    =
 
-# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
-# with syntax highlighting in the RTF output.
-#
-# Note that which sources are shown also depends on other settings such as
-# SOURCE_BROWSER.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_RTF is set to YES.
-
-RTF_SOURCE_CODE        = NO
-
 #---------------------------------------------------------------------------
 # Configuration options related to the man page output
 #---------------------------------------------------------------------------
@@ -1934,6 +2183,13 @@ XML_OUTPUT             = xml
 
 XML_PROGRAMLISTING     = YES
 
+# If the XML_NS_MEMB_FILE_SCOPE tag is set to YES, doxygen will include
+# namespace members in file scope as well, matching the HTML output.
+# The default value is: NO.
+# This tag requires that the tag GENERATE_XML is set to YES.
+
+XML_NS_MEMB_FILE_SCOPE = NO
+
 #---------------------------------------------------------------------------
 # Configuration options related to the DOCBOOK output
 #---------------------------------------------------------------------------
@@ -1952,23 +2208,14 @@ GENERATE_DOCBOOK       = NO
 
 DOCBOOK_OUTPUT         = docbook
 
-# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
-# program listings (including syntax highlighting and cross-referencing
-# information) to the DOCBOOK output. Note that enabling this will significantly
-# increase the size of the DOCBOOK output.
-# The default value is: NO.
-# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
-
-DOCBOOK_PROGRAMLISTING = NO
-
 #---------------------------------------------------------------------------
 # Configuration options for the AutoGen Definitions output
 #---------------------------------------------------------------------------
 
 # If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
-# AutoGen Definitions (see http://autogen.sf.net) file that captures the
-# structure of the code including all documentation. Note that this feature is
-# still experimental and incomplete at the moment.
+# AutoGen Definitions (see http://autogen.sourceforge.net/) file that captures
+# the structure of the code including all documentation. Note that this feature
+# is still experimental and incomplete at the moment.
 # The default value is: NO.
 
 GENERATE_AUTOGEN_DEF   = NO
@@ -2047,7 +2294,8 @@ SEARCH_INCLUDES        = YES
 
 # The INCLUDE_PATH tag can be used to specify one or more directories that
 # contain include files that are not input files but should be processed by the
-# preprocessor.
+# preprocessor. Note that the INCLUDE_PATH is not recursive, so the setting of
+# RECURSIVE has no effect here.
 # This tag requires that the tag SEARCH_INCLUDES is set to YES.
 
 INCLUDE_PATH           =
@@ -2153,15 +2401,6 @@ EXTERNAL_PAGES         = YES
 # Configuration options related to the dot tool
 #---------------------------------------------------------------------------
 
-# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
-# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
-# NO turns the diagrams off. Note that this option also works with HAVE_DOT
-# disabled, but it is recommended to install and use dot, since it yields more
-# powerful graphs.
-# The default value is: YES.
-
-CLASS_DIAGRAMS         = YES
-
 # You can include diagrams made with dia in doxygen documentation. Doxygen will
 # then run dia to produce the diagram and insert it in the documentation. The
 # DIA_PATH tag allows you to specify the directory where the dia binary resides.
@@ -2194,35 +2433,50 @@ HAVE_DOT               = YES
 
 DOT_NUM_THREADS        = 0
 
-# When you want a differently looking font in the dot files that doxygen
-# generates you can specify the font name using DOT_FONTNAME. You need to make
-# sure dot is able to find the font, which can be done by putting it in a
-# standard location or by setting the DOTFONTPATH environment variable or by
-# setting DOT_FONTPATH to the directory containing the font.
-# The default value is: Helvetica.
+# DOT_COMMON_ATTR is common attributes for nodes, edges and labels of
+# subgraphs. When you want a differently looking font in the dot files that
+# doxygen generates you can specify fontname, fontcolor and fontsize attributes.
+# For details please see <a href=https://graphviz.org/doc/info/attrs.html>Node,
+# Edge and Graph Attributes specification</a> You need to make sure dot is able
+# to find the font, which can be done by putting it in a standard location or by
+# setting the DOTFONTPATH environment variable or by setting DOT_FONTPATH to the
+# directory containing the font. Default graphviz fontsize is 14.
+# The default value is: fontname=Helvetica,fontsize=10.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_COMMON_ATTR        = "fontname=Helvetica,fontsize=10"
+
+# DOT_EDGE_ATTR is concatenated with DOT_COMMON_ATTR. For elegant style you can
+# add 'arrowhead=open, arrowtail=open, arrowsize=0.5'. <a
+# href=https://graphviz.org/doc/info/arrows.html>Complete documentation about
+# arrows shapes.</a>
+# The default value is: labelfontname=Helvetica,labelfontsize=10.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_FONTNAME           =
+DOT_EDGE_ATTR          = "labelfontname=Helvetica,labelfontsize=10"
 
-# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
-# dot graphs.
-# Minimum value: 4, maximum value: 24, default value: 10.
+# DOT_NODE_ATTR is concatenated with DOT_COMMON_ATTR. For view without boxes
+# around nodes set 'shape=plain' or 'shape=plaintext' <a
+# href=https://www.graphviz.org/doc/info/shapes.html>Shapes specification</a>
+# The default value is: shape=box,height=0.2,width=0.4.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
-DOT_FONTSIZE           = 10
+DOT_NODE_ATTR          = "shape=box,height=0.2,width=0.4"
 
-# By default doxygen will tell dot to use the default font as specified with
-# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
-# the path where dot can find it using this tag.
+# You can set the path where dot can find font specified with fontname in
+# DOT_COMMON_ATTR and others dot attributes.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_FONTPATH           =
 
-# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
-# each documented class showing the direct and indirect inheritance relations.
-# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
+# If the CLASS_GRAPH tag is set to YES (or GRAPH) then doxygen will generate a
+# graph for each documented class showing the direct and indirect inheritance
+# relations. In case HAVE_DOT is set as well dot will be used to draw the graph,
+# otherwise the built-in generator will be used. If the CLASS_GRAPH tag is set
+# to TEXT the direct and indirect inheritance relations will be shown as texts /
+# links.
+# Possible values are: NO, YES, TEXT and GRAPH.
 # The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
 
 CLASS_GRAPH            = YES
 
@@ -2236,7 +2490,8 @@ CLASS_GRAPH            = YES
 COLLABORATION_GRAPH    = NO
 
 # If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
-# groups, showing the direct groups dependencies.
+# groups, showing the direct groups dependencies. See also the chapter Grouping
+# in the manual.
 # The default value is: YES.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
@@ -2259,10 +2514,32 @@ UML_LOOK               = NO
 # but if the number exceeds 15, the total amount of fields shown is limited to
 # 10.
 # Minimum value: 0, maximum value: 100, default value: 10.
-# This tag requires that the tag HAVE_DOT is set to YES.
+# This tag requires that the tag UML_LOOK is set to YES.
 
 UML_LIMIT_NUM_FIELDS   = 10
 
+# If the DOT_UML_DETAILS tag is set to NO, doxygen will show attributes and
+# methods without types and arguments in the UML graphs. If the DOT_UML_DETAILS
+# tag is set to YES, doxygen will add type and arguments for attributes and
+# methods in the UML graphs. If the DOT_UML_DETAILS tag is set to NONE, doxygen
+# will not generate fields with class member information in the UML graphs. The
+# class diagrams will look similar to the default class diagrams but using UML
+# notation for the relationships.
+# Possible values are: NO, YES and NONE.
+# The default value is: NO.
+# This tag requires that the tag UML_LOOK is set to YES.
+
+DOT_UML_DETAILS        = NO
+
+# The DOT_WRAP_THRESHOLD tag can be used to set the maximum number of characters
+# to display on a single line. If the actual line length exceeds this threshold
+# significantly it will wrapped across multiple lines. Some heuristics are apply
+# to avoid ugly line breaks.
+# Minimum value: 0, maximum value: 1000, default value: 17.
+# This tag requires that the tag HAVE_DOT is set to YES.
+
+DOT_WRAP_THRESHOLD     = 17
+
 # If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
 # collaboration graphs will show the relations between templates and their
 # instances.
@@ -2329,6 +2606,13 @@ GRAPHICAL_HIERARCHY    = NO
 
 DIRECTORY_GRAPH        = NO
 
+# The DIR_GRAPH_MAX_DEPTH tag can be used to limit the maximum number of levels
+# of child directories generated in directory dependency graphs by dot.
+# Minimum value: 1, maximum value: 25, default value: 1.
+# This tag requires that the tag DIRECTORY_GRAPH is set to YES.
+
+DIR_GRAPH_MAX_DEPTH    = 1
+
 # The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
 # generated by dot. For an explanation of the image formats see the section
 # output formats in the documentation of the dot tool (Graphviz (see:
@@ -2382,13 +2666,18 @@ MSCFILE_DIRS           =
 DIAFILE_DIRS           =
 
 # When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
-# path where java can find the plantuml.jar file. If left blank, it is assumed
-# PlantUML is not used or called during a preprocessing step. Doxygen will
-# generate a warning when it encounters a \startuml command in this case and
-# will not generate output for the diagram.
+# path where java can find the plantuml.jar file or to the filename of jar file
+# to be used. If left blank, it is assumed PlantUML is not used or called during
+# a preprocessing step. Doxygen will generate a warning when it encounters a
+# \startuml command in this case and will not generate output for the diagram.
 
 PLANTUML_JAR_PATH      =
 
+# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
+# configuration file for plantuml.
+
+PLANTUML_CFG_FILE      =
+
 # When using plantuml, the specified paths are searched for files specified by
 # the !include statement in a plantuml block.
 
@@ -2418,18 +2707,6 @@ DOT_GRAPH_MAX_NODES    = 50
 
 MAX_DOT_GRAPH_DEPTH    = 0
 
-# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
-# background. This is disabled by default, because dot on Windows does not seem
-# to support this out of the box.
-#
-# Warning: Depending on the platform used, enabling this option may lead to
-# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
-# read).
-# The default value is: NO.
-# This tag requires that the tag HAVE_DOT is set to YES.
-
-DOT_TRANSPARENT        = YES
-
 # Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
 # files in one run (i.e. multiple -o and -T options on the command line). This
 # makes dot run faster, but since only newer versions of dot (>1.8.10) support
@@ -2442,14 +2719,18 @@ DOT_MULTI_TARGETS      = NO
 # If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
 # explaining the meaning of the various boxes and arrows in the dot generated
 # graphs.
+# Note: This tag requires that UML_LOOK isn't set, i.e. the doxygen internal
+# graphical representation for inheritance and collaboration diagrams is used.
 # The default value is: YES.
 # This tag requires that the tag HAVE_DOT is set to YES.
 
 GENERATE_LEGEND        = NO
 
-# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
+# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate
 # files that are used to generate the various graphs.
+#
+# Note: This setting is not only used for dot files but also for msc temporary
+# files.
 # The default value is: YES.
-# This tag requires that the tag HAVE_DOT is set to YES.
 
 DOT_CLEANUP            = YES
index c38135dabef7122a7a31a7261b2ea1be94cea0b2..85ec8ee2f9e2afabf8d09110782c4561ee6cb91b 100644 (file)
@@ -87,7 +87,7 @@ if __name__ == "__main__":
         juce_modules = args.subdirs.split(",")
     else:
         juce_modules = []
-        for item in os.listdir(args.source_dir):
+        for item in sorted(os.listdir(args.source_dir)):
             if os.path.isdir(os.path.join(args.source_dir, item)):
                 juce_modules.append(item)
 
@@ -136,7 +136,7 @@ if __name__ == "__main__":
 
         # Create a list of the directories in the module that we can use as
         # subgroups and create the Doxygen group hierarchy string.
-        dir_contents = os.listdir(module_path)
+        dir_contents = sorted(os.listdir(module_path))
         # Ignore "native" folders as these are excluded by doxygen.
         try:
             dir_contents.remove("native")
index dc75464ee9fedd2253da5e0e4b664cadb6fa667d..d706170dc2928f399811a60f294699ef858273f0 100644 (file)
@@ -45,10 +45,12 @@ public:
         clear();\r
     }\r
 \r
-    void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
-                                float** outputChannelData, int numOutputChannels,\r
-                                int numberOfSamples) override\r
+    void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+                                           float* const* outputChannelData, int numOutputChannels,\r
+                                           int numberOfSamples, const AudioIODeviceCallbackContext& context) override\r
     {\r
+        ignoreUnused (context);\r
+\r
         for (int i = 0; i < numberOfSamples; ++i)\r
         {\r
             float inputSample = 0;\r
index 49ccc278720c9c2fa6dac9af64b2a64556b9c0df..9fa1d5c3a087fcfab074bd9da111855d56406f8a 100644 (file)
@@ -25,7 +25,7 @@ using namespace dsp;
 struct DSPDemoParameterBase    : public ChangeBroadcaster\r
 {\r
     DSPDemoParameterBase (const String& labelName) : name (labelName) {}\r
-    virtual ~DSPDemoParameterBase() {}\r
+    virtual ~DSPDemoParameterBase() = default;\r
 \r
     virtual Component* getComponent() = 0;\r
 \r
@@ -142,7 +142,7 @@ public:
         loadURL (u);\r
     }\r
 \r
-    URL getCurrentURL()    { return currentURL; }\r
+    URL getCurrentURL() const   { return currentURL; }\r
 \r
     void setTransportSource (AudioTransportSource* newSource)\r
     {\r
@@ -189,21 +189,7 @@ private:
 \r
         currentURL = u;\r
 \r
-        InputSource* inputSource = nullptr;\r
-\r
-       #if ! JUCE_IOS\r
-        if (u.isLocalFile())\r
-        {\r
-            inputSource = new FileInputSource (u.getLocalFile());\r
-        }\r
-        else\r
-       #endif\r
-        {\r
-            if (inputSource == nullptr)\r
-                inputSource = new URLInputSource (u);\r
-        }\r
-\r
-        thumbnail.setSource (inputSource);\r
+        thumbnail.setSource (makeInputSource (u).release());\r
 \r
         if (notify)\r
             sendChangeMessage();\r
@@ -407,33 +393,27 @@ public:
         transportSource.reset();\r
         readerSource.reset();\r
 \r
-        AudioFormatReader* newReader = nullptr;\r
+        auto source = makeInputSource (fileToPlay);\r
 \r
-       #if ! JUCE_IOS\r
-        if (fileToPlay.isLocalFile())\r
-        {\r
-            newReader = formatManager.createReaderFor (fileToPlay.getLocalFile());\r
-        }\r
-        else\r
-       #endif\r
-        {\r
-            if (newReader == nullptr)\r
-                newReader = formatManager.createReaderFor (fileToPlay.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)));\r
-        }\r
+        if (source == nullptr)\r
+            return false;\r
 \r
-        reader.reset (newReader);\r
+        auto stream = rawToUniquePtr (source->createInputStream());\r
 \r
-        if (reader.get() != nullptr)\r
-        {\r
-            readerSource.reset (new AudioFormatReaderSource (reader.get(), false));\r
-            readerSource->setLooping (loopState.getValue());\r
+        if (stream == nullptr)\r
+            return false;\r
 \r
-            init();\r
+        reader = rawToUniquePtr (formatManager.createReaderFor (std::move (stream)));\r
 \r
-            return true;\r
-        }\r
+        if (reader == nullptr)\r
+            return false;\r
+\r
+        readerSource.reset (new AudioFormatReaderSource (reader.get(), false));\r
+        readerSource->setLooping (loopState.getValue());\r
+\r
+        init();\r
 \r
-        return false;\r
+        return true;\r
     }\r
 \r
     void togglePlay()\r
@@ -613,7 +593,7 @@ private:
                                       {\r
                                           if (fc.getURLResults().size() > 0)\r
                                           {\r
-                                              auto u = fc.getURLResult();\r
+                                              const auto u = fc.getURLResult();\r
 \r
                                               if (! audioFileReader.loadURL (u))\r
                                                   NativeMessageBox::showAsync (MessageBoxOptions()\r
index bfc1c5d2862ed6d65cd01cf1174df2d1c6173303..ffdfc3631c930a0500cf7f0ef82843cbe47e6316 100644 (file)
@@ -242,4 +242,19 @@ struct SlowerBouncingNumber  : public BouncingNumber
     }\r
 };\r
 \r
+inline std::unique_ptr<InputSource> makeInputSource (const URL& url)\r
+{\r
+   #if JUCE_ANDROID\r
+    if (auto doc = AndroidDocument::fromDocument (url))\r
+        return std::make_unique<AndroidDocumentInputSource> (doc);\r
+   #endif\r
+\r
+   #if ! JUCE_IOS\r
+    if (url.isLocalFile())\r
+        return std::make_unique<FileInputSource> (url.getLocalFile());\r
+   #endif\r
+\r
+    return std::make_unique<URLInputSource> (url);\r
+}\r
+\r
 #endif   // PIP_DEMO_UTILITIES_INCLUDED\r
index 171accb4364a1c1bc2d74bdbce6933f527494276..cd47e94a35a2c22eaf5bddc127d72ea5c0e61c8c 100644 (file)
@@ -136,9 +136,12 @@ public:
 \r
     void audioDeviceStopped() override {}\r
 \r
-    void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
-                                float** outputChannelData, int numOutputChannels, int numSamples) override\r
+    void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+                                           float* const* outputChannelData, int numOutputChannels,\r
+                                           int numSamples, const AudioIODeviceCallbackContext& context) override\r
     {\r
+        ignoreUnused (context);\r
+\r
         const ScopedLock sl (lock);\r
 \r
         if (testIsRunning)\r
index dd457ce5c17e519f606325144315a86f259ca4e8..6d317f446604ee34b3ddf51b3fe035aab80fee36 100644 (file)
 \r
 #include "../Assets/DemoUtilities.h"\r
 \r
-inline std::unique_ptr<InputSource> makeInputSource (const URL& url)\r
-{\r
-   #if JUCE_ANDROID\r
-    if (auto doc = AndroidDocument::fromDocument (url))\r
-        return std::make_unique<AndroidDocumentInputSource> (doc);\r
-   #endif\r
-\r
-   #if ! JUCE_IOS\r
-    if (url.isLocalFile())\r
-        return std::make_unique<FileInputSource> (url.getLocalFile());\r
-   #endif\r
-\r
-    return std::make_unique<URLInputSource> (url);\r
-}\r
-\r
-//==============================================================================\r
 class DemoThumbnailComp  : public Component,\r
                            public ChangeListener,\r
                            public FileDragAndDropTarget,\r
@@ -325,7 +309,7 @@ public:
         // audio setup\r
         formatManager.registerBasicFormats();\r
 \r
-        thread.startThread (3);\r
+        thread.startThread (Thread::Priority::normal);\r
 \r
        #ifndef JUCE_DEMO_RUNNER\r
         RuntimePermissions::request (RuntimePermissions::recordAudio,\r
index 6bfa622eb356497f6c68585cc804a1a3adbf52fb..38bf15b7d7b825245b0ccdd47623d65c1f1db1d8 100644 (file)
@@ -134,10 +134,12 @@ public:
         sampleRate = 0;\r
     }\r
 \r
-    void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
-                                float** outputChannelData, int numOutputChannels,\r
-                                int numSamples) override\r
+    void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+                                           float* const* outputChannelData, int numOutputChannels,\r
+                                           int numSamples, const AudioIODeviceCallbackContext& context) override\r
     {\r
+        ignoreUnused (context);\r
+\r
         const ScopedLock sl (writerLock);\r
 \r
         if (activeWriter.load() != nullptr && numInputChannels >= thumbnail.getNumChannels())\r
index 35a51c4b04cdcf3e1750cff553319a7b559169be..10615ee7336d03aec68f5bf24fc4fb2784efd2f8 100644 (file)
@@ -689,10 +689,12 @@ public:
     }\r
 \r
     //==============================================================================\r
-    void audioDeviceIOCallback (const float** /*inputChannelData*/, int /*numInputChannels*/,\r
-                                float** outputChannelData, int numOutputChannels,\r
-                                int numSamples) override\r
+    void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+                                           float* const* outputChannelData, int numOutputChannels,\r
+                                           int numSamples, const AudioIODeviceCallbackContext& context) override\r
     {\r
+        ignoreUnused (inputChannelData, numInputChannels, context);\r
+\r
         AudioBuffer<float> buffer (outputChannelData, numOutputChannels, numSamples);\r
         buffer.clear();\r
 \r
index 585547ffb8b935052927a45db4181495a4e831af..5b9e96454320f605c048167251057b56d8ac51d1 100644 (file)
@@ -1,8 +1,10 @@
-# Automatically generated makefile, created by the Projucer
+# Automatically generated CMakeLists, created by the Projucer
 # Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
 
 cmake_minimum_required(VERSION 3.4.1)
 
+project(juce_jni_project)
+
 set(BINARY_NAME "juce_jni")
 
 set(OBOE_DIR "../../../../../modules/juce_audio_devices/native/oboe")
@@ -12,7 +14,7 @@ add_subdirectory (${OBOE_DIR} ./oboe)
 add_library("cpufeatures" STATIC "${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c")
 set_source_files_properties("${ANDROID_NDK}/sources/android/cpufeatures/cpu-features.c" PROPERTIES COMPILE_FLAGS "-Wno-sign-conversion -Wno-gnu-statement-expression")
 
-add_definitions([[-DJUCE_ANDROID=1]] [[-DJUCE_ANDROID_API_VERSION=23]] [[-DJUCE_PUSH_NOTIFICATIONS=1]] [[-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY="com/rmsl/juce/JuceActivity"]] [[-DJUCE_CONTENT_SHARING=1]] [[-DJUCE_ANDROID_GL_ES_VERSION_3_0=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.2]] [[-DJUCE_APP_VERSION_HEX=0x70002]])
+add_definitions([[-DJUCE_ANDROID=1]] [[-DJUCE_ANDROID_API_VERSION=23]] [[-DJUCE_PUSH_NOTIFICATIONS=1]] [[-DJUCE_PUSH_NOTIFICATIONS_ACTIVITY="com/rmsl/juce/JuceActivity"]] [[-DJUCE_CONTENT_SHARING=1]] [[-DJUCE_ANDROID_GL_ES_VERSION_3_0=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.5]] [[-DJUCE_APP_VERSION_HEX=0x70005]])
 
 include_directories( AFTER
     "../../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src"
@@ -32,9 +34,9 @@ include_directories( AFTER
 enable_language(ASM)
 
 if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG")
-    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_analytics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_box2d=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1]] [[-DJUCE_MODULE_AVAILABLE_juce_video=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_USE_MP3AUDIOFORMAT=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0]] [[-DJUCE_STRICT_REFCOUNTEDPOINTER=1]] [[-DJUCE_USE_CAMERA=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.2]] [[-DJUCE_APP_VERSION_HEX=0x70002]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
+    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70005]] [[-DJUCE_MODULE_AVAILABLE_juce_analytics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_box2d=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1]] [[-DJUCE_MODULE_AVAILABLE_juce_video=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_USE_MP3AUDIOFORMAT=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0]] [[-DJUCE_STRICT_REFCOUNTEDPOINTER=1]] [[-DJUCE_USE_CAMERA=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.5]] [[-DJUCE_APP_VERSION_HEX=0x70005]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
 elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE")
-    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_analytics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_box2d=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1]] [[-DJUCE_MODULE_AVAILABLE_juce_video=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_USE_MP3AUDIOFORMAT=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0]] [[-DJUCE_STRICT_REFCOUNTEDPOINTER=1]] [[-DJUCE_USE_CAMERA=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.2]] [[-DJUCE_APP_VERSION_HEX=0x70002]] [[-DNDEBUG=1]])
+    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70005]] [[-DJUCE_MODULE_AVAILABLE_juce_analytics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_box2d=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1]] [[-DJUCE_MODULE_AVAILABLE_juce_video=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_USE_MP3AUDIOFORMAT=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0]] [[-DJUCE_STRICT_REFCOUNTEDPOINTER=1]] [[-DJUCE_USE_CAMERA=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEMO_RUNNER=1]] [[-DJUCE_UNIT_TESTS=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=7.0.5]] [[-DJUCE_APP_VERSION_HEX=0x70005]] [[-DNDEBUG=1]])
 else()
     message( FATAL_ERROR "No matching build-configuration found." )
 endif()
@@ -64,6 +66,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_analytics/destinations/juce_ThreadedAnalyticsDestination.h"
     "../../../../../modules/juce_analytics/juce_analytics.cpp"
     "../../../../../modules/juce_analytics/juce_analytics.h"
+    "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp"
     "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.h"
@@ -82,6 +85,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPConverters.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPDispatcher.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPFactory.h"
+    "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"
@@ -138,6 +142,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_basics/sources/juce_MemoryAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.h"
+    "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h"
@@ -372,7 +377,6 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
-    "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
@@ -782,6 +786,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h"
     "../../../../../modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h"
+    "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.mm"
@@ -1046,6 +1051,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/native/juce_mac_Strings.mm"
     "../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
     "../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+    "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
     "../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
     "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
     "../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
@@ -1203,6 +1209,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_data_structures/app_properties/juce_ApplicationProperties.h"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.h"
+    "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.h"
@@ -1742,6 +1749,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAWindowProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_WindowsUIAWrapper.h"
+    "../../../../../modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h"
@@ -1761,6 +1769,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+    "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
     "../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
     "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
     "../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
@@ -1845,6 +1854,8 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.h"
@@ -1889,6 +1900,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"
+    "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.h"
     "../../../../../modules/juce_gui_extra/native/juce_android_PushNotifications.cpp"
     "../../../../../modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"
@@ -2036,6 +2048,7 @@ set_source_files_properties(
     "../../../../../modules/juce_analytics/destinations/juce_ThreadedAnalyticsDestination.h"
     "../../../../../modules/juce_analytics/juce_analytics.cpp"
     "../../../../../modules/juce_analytics/juce_analytics.h"
+    "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp"
     "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.h"
@@ -2054,6 +2067,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPConverters.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPDispatcher.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPFactory.h"
+    "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"
@@ -2110,6 +2124,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_basics/sources/juce_MemoryAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.h"
+    "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h"
@@ -2344,7 +2359,6 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
-    "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
@@ -2754,6 +2768,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h"
     "../../../../../modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h"
+    "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.mm"
@@ -3018,6 +3033,7 @@ set_source_files_properties(
     "../../../../../modules/juce_core/native/juce_mac_Strings.mm"
     "../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
     "../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+    "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
     "../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
     "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
     "../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
@@ -3175,6 +3191,7 @@ set_source_files_properties(
     "../../../../../modules/juce_data_structures/app_properties/juce_ApplicationProperties.h"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.h"
+    "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.h"
@@ -3714,6 +3731,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAWindowProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_WindowsUIAWrapper.h"
+    "../../../../../modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h"
@@ -3733,6 +3751,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+    "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
     "../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
     "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
     "../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
@@ -3817,6 +3836,8 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.h"
@@ -3861,6 +3882,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"
+    "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.h"
     "../../../../../modules/juce_gui_extra/native/juce_android_PushNotifications.cpp"
     "../../../../../modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"
@@ -3971,14 +3993,12 @@ set_source_files_properties(
     "../../../JuceLibraryCode/JuceHeader.h"
     PROPERTIES HEADER_FILE_ONLY TRUE)
 
-target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
-
 if( JUCE_BUILD_CONFIGURATION MATCHES "DEBUG" )
-    target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override)
+    target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override "-fsigned-char" )
 endif()
 
 if( JUCE_BUILD_CONFIGURATION MATCHES "RELEASE" )
-    target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override)
+    target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override "-fsigned-char" )
 endif()
 
 find_library(log "log")
index 6b3be277d473b61ab4bcfbd593bbea799996eb0d..a120c191f34d92cbb78b9a2cce5c46ac484a35f5 100644 (file)
@@ -1,7 +1,8 @@
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 31
+    compileSdkVersion 33
+    namespace "com.rmsl.jucedemorunner"
     externalNativeBuild {
         cmake {
             path "CMakeLists.txt"
@@ -20,10 +21,10 @@ android {
     defaultConfig {
         applicationId "com.rmsl.jucedemorunner"
         minSdkVersion    23
-        targetSdkVersion 31
+        targetSdkVersion 33
         externalNativeBuild {
             cmake {
-                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF"
+                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=17", "-DCMAKE_CXX_EXTENSIONS=OFF"
             }
         }
     }
@@ -51,21 +52,25 @@ android {
             }
             externalNativeBuild {
                 cmake {
-                    arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-O0", "-DCMAKE_C_FLAGS_DEBUG=-O0"
+                    cFlags    "-O0"
+                    cppFlags  "-O0"
+                    arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG"
                 }
             }
 
             dimension "default"
-       }
+        }
         release_ {
             externalNativeBuild {
                 cmake {
-                    arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-O3", "-DCMAKE_C_FLAGS_RELEASE=-O3"
+                    cFlags    "-O3"
+                    cppFlags  "-O3"
+                    arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE"
                 }
             }
 
             dimension "default"
-       }
+        }
     }
 
     variantFilter { variant ->
index c8b3a2a6b8c6ab8e522e67436dea1196b2396fd5..7500ac43f5d368e5e0d2fe4aa09efab462691580 100644 (file)
@@ -1,22 +1,27 @@
 <?xml version="1.0" encoding="utf-8"?>
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="7.0.2"
-          package="com.rmsl.jucedemorunner">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="7.0.5">
   <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"
                     android:xlargeScreens="true"/>
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
-  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
-  <uses-permission android:name="android.permission.BLUETOOTH"/>
+  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
+  <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
+  <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
+  <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
+  <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
   <uses-permission android:name="android.permission.CAMERA"/>
   <uses-permission android:name="android.permission.RECORD_AUDIO"/>
   <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-feature android:glEsVersion="0x00030000" android:required="true"/>
   <application android:label="@string/app_name" android:name="com.rmsl.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
-    <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
+    <activity android:name="com.rmsl.juce.JuceActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|navigation"
               android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"
               android:exported="true">
       <intent-filter>
index dc75464ee9fedd2253da5e0e4b664cadb6fa667d..d706170dc2928f399811a60f294699ef858273f0 100644 (file)
@@ -45,10 +45,12 @@ public:
         clear();\r
     }\r
 \r
-    void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
-                                float** outputChannelData, int numOutputChannels,\r
-                                int numberOfSamples) override\r
+    void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+                                           float* const* outputChannelData, int numOutputChannels,\r
+                                           int numberOfSamples, const AudioIODeviceCallbackContext& context) override\r
     {\r
+        ignoreUnused (context);\r
+\r
         for (int i = 0; i < numberOfSamples; ++i)\r
         {\r
             float inputSample = 0;\r
index 49ccc278720c9c2fa6dac9af64b2a64556b9c0df..9fa1d5c3a087fcfab074bd9da111855d56406f8a 100644 (file)
@@ -25,7 +25,7 @@ using namespace dsp;
 struct DSPDemoParameterBase    : public ChangeBroadcaster\r
 {\r
     DSPDemoParameterBase (const String& labelName) : name (labelName) {}\r
-    virtual ~DSPDemoParameterBase() {}\r
+    virtual ~DSPDemoParameterBase() = default;\r
 \r
     virtual Component* getComponent() = 0;\r
 \r
@@ -142,7 +142,7 @@ public:
         loadURL (u);\r
     }\r
 \r
-    URL getCurrentURL()    { return currentURL; }\r
+    URL getCurrentURL() const   { return currentURL; }\r
 \r
     void setTransportSource (AudioTransportSource* newSource)\r
     {\r
@@ -189,21 +189,7 @@ private:
 \r
         currentURL = u;\r
 \r
-        InputSource* inputSource = nullptr;\r
-\r
-       #if ! JUCE_IOS\r
-        if (u.isLocalFile())\r
-        {\r
-            inputSource = new FileInputSource (u.getLocalFile());\r
-        }\r
-        else\r
-       #endif\r
-        {\r
-            if (inputSource == nullptr)\r
-                inputSource = new URLInputSource (u);\r
-        }\r
-\r
-        thumbnail.setSource (inputSource);\r
+        thumbnail.setSource (makeInputSource (u).release());\r
 \r
         if (notify)\r
             sendChangeMessage();\r
@@ -407,33 +393,27 @@ public:
         transportSource.reset();\r
         readerSource.reset();\r
 \r
-        AudioFormatReader* newReader = nullptr;\r
+        auto source = makeInputSource (fileToPlay);\r
 \r
-       #if ! JUCE_IOS\r
-        if (fileToPlay.isLocalFile())\r
-        {\r
-            newReader = formatManager.createReaderFor (fileToPlay.getLocalFile());\r
-        }\r
-        else\r
-       #endif\r
-        {\r
-            if (newReader == nullptr)\r
-                newReader = formatManager.createReaderFor (fileToPlay.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)));\r
-        }\r
+        if (source == nullptr)\r
+            return false;\r
 \r
-        reader.reset (newReader);\r
+        auto stream = rawToUniquePtr (source->createInputStream());\r
 \r
-        if (reader.get() != nullptr)\r
-        {\r
-            readerSource.reset (new AudioFormatReaderSource (reader.get(), false));\r
-            readerSource->setLooping (loopState.getValue());\r
+        if (stream == nullptr)\r
+            return false;\r
 \r
-            init();\r
+        reader = rawToUniquePtr (formatManager.createReaderFor (std::move (stream)));\r
 \r
-            return true;\r
-        }\r
+        if (reader == nullptr)\r
+            return false;\r
+\r
+        readerSource.reset (new AudioFormatReaderSource (reader.get(), false));\r
+        readerSource->setLooping (loopState.getValue());\r
+\r
+        init();\r
 \r
-        return false;\r
+        return true;\r
     }\r
 \r
     void togglePlay()\r
@@ -613,7 +593,7 @@ private:
                                       {\r
                                           if (fc.getURLResults().size() > 0)\r
                                           {\r
-                                              auto u = fc.getURLResult();\r
+                                              const auto u = fc.getURLResult();\r
 \r
                                               if (! audioFileReader.loadURL (u))\r
                                                   NativeMessageBox::showAsync (MessageBoxOptions()\r
index bfc1c5d2862ed6d65cd01cf1174df2d1c6173303..ffdfc3631c930a0500cf7f0ef82843cbe47e6316 100644 (file)
@@ -242,4 +242,19 @@ struct SlowerBouncingNumber  : public BouncingNumber
     }\r
 };\r
 \r
+inline std::unique_ptr<InputSource> makeInputSource (const URL& url)\r
+{\r
+   #if JUCE_ANDROID\r
+    if (auto doc = AndroidDocument::fromDocument (url))\r
+        return std::make_unique<AndroidDocumentInputSource> (doc);\r
+   #endif\r
+\r
+   #if ! JUCE_IOS\r
+    if (url.isLocalFile())\r
+        return std::make_unique<FileInputSource> (url.getLocalFile());\r
+   #endif\r
+\r
+    return std::make_unique<URLInputSource> (url);\r
+}\r
+\r
 #endif   // PIP_DEMO_UTILITIES_INCLUDED\r
index ee98c096888d52d441152343876cf1066882fe6a..8e2533a6a8e084f3c9a1cd90818d4b330cbde43d 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
        mavenCentral()
    }
    dependencies {
-       classpath 'com.android.tools.build:gradle:7.0.0'
+       classpath 'com.android.tools.build:gradle:7.3.0'
    }
 }
 
index 80082ba57b11f2c7cdc838256a00336bbde9d498..702c227cd3ad7b11fe3589f2c2d97dbf29504ec6 100644 (file)
@@ -1 +1 @@
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
\ No newline at end of file
index 316d4b10c112c08a60aa68a791913347d324f137..faa2c752954f73303dc941fb15450edfdbe48e16 100644 (file)
@@ -39,12 +39,12 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_box2d=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_USE_MP3AUDIOFORMAT=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_USE_CAMERA=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.2" "-DJUCE_APP_VERSION_HEX=0x70002" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_box2d=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_USE_MP3AUDIOFORMAT=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_USE_CAMERA=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.5" "-DJUCE_APP_VERSION_HEX=0x70005" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := DemoRunner
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
@@ -60,12 +60,12 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_box2d=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_USE_MP3AUDIOFORMAT=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_USE_CAMERA=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.2" "-DJUCE_APP_VERSION_HEX=0x70002" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_box2d=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_USE_MP3AUDIOFORMAT=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_USE_CAMERA=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_DEMO_RUNNER=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.5" "-DJUCE_APP_VERSION_HEX=0x70005" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := DemoRunner
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
index c647f0b0af5b1c917883dc44ab0ed41a8266b22f..f69455f9aca0576d2b63a98b6c8ead439d61d219 100644 (file)
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                69330F27DD2C71609336C7D2 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                DEAD_CODE_STRIPPING = YES;
                                        "NDEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_analytics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_DEMO_RUNNER=1",
                                        "JUCE_UNIT_TESTS=1",
                                        "JUCER_XCODE_MAC_F6D2F4CF=1",
-                                       "JUCE_APP_VERSION=7.0.2",
-                                       "JUCE_APP_VERSION_HEX=0x70002",
+                                       "JUCE_APP_VERSION=7.0.5",
+                                       "JUCE_APP_VERSION_HEX=0x70005",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
                                LLVM_LTO = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                B18D059E5616FA729F764229 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                COPY_PHASE_STRIP = NO;
                                        "DEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_analytics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_DEMO_RUNNER=1",
                                        "JUCE_UNIT_TESTS=1",
                                        "JUCER_XCODE_MAC_F6D2F4CF=1",
-                                       "JUCE_APP_VERSION=7.0.2",
-                                       "JUCE_APP_VERSION_HEX=0x70002",
+                                       "JUCE_APP_VERSION=7.0.5",
+                                       "JUCE_APP_VERSION_HEX=0x70005",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                INFOPLIST_FILE = Info-App.plist;
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
index fecf91cc5ddabf598bb1d5fced6dacbd9f11d23b..f2a852d1900a5e705879b2f980ccb3f70f0dd9e4 100644 (file)
@@ -24,9 +24,9 @@
     <key>CFBundleSignature</key>\r
     <string>????</string>\r
     <key>CFBundleShortVersionString</key>\r
-    <string>7.0.2</string>\r
+    <string>7.0.5</string>\r
     <key>CFBundleVersion</key>\r
-    <string>7.0.2</string>\r
+    <string>7.0.5</string>\r
     <key>NSHumanReadableCopyright</key>\r
     <string>Copyright (c) 2020 - Raw Material Software Limited</string>\r
     <key>NSHighResolutionCapable</key>\r
index 1d4e3d0806b974cfe5aa18ea364403b49366ad27..187c40f26619171583639248d6f4b382cdff80fd 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 8ab0de032bc2345c8cbdcd624944560d458ae8fa..57a30d71d1867fef1d5d0a73721dfc7427b75847 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <Filter>JUCE Modules\juce_analytics</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 3adeec39e7b6582f0829b4c72ce51141ad786795..d1e516af447a694ed9b3cef6d90f71c687555a88 100644 (file)
@@ -9,7 +9,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  7,0,2,0\r
+FILEVERSION  7,0,5,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -18,9 +18,9 @@ BEGIN
       VALUE "CompanyName",  "Raw Material Software Limited\0"\r
       VALUE "LegalCopyright",  "Copyright (c) 2020 - Raw Material Software Limited\0"\r
       VALUE "FileDescription",  "DemoRunner\0"\r
-      VALUE "FileVersion",  "7.0.2\0"\r
+      VALUE "FileVersion",  "7.0.5\0"\r
       VALUE "ProductName",  "DemoRunner\0"\r
-      VALUE "ProductVersion",  "7.0.2\0"\r
+      VALUE "ProductVersion",  "7.0.5\0"\r
     END\r
   END\r
 \r
index 7bb91c62fbf10338dd869b61d46a7d9e068c283a..08a4d4c8a07f015831146239f1d836cf0240e67a 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 453ecdeb0c6d81efd3a1735744af54f9cb1d6c39..c91a76b8c83a6c6a1e3982b10bb829ead8b6f9f8 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <Filter>JUCE Modules\juce_analytics</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 3adeec39e7b6582f0829b4c72ce51141ad786795..d1e516af447a694ed9b3cef6d90f71c687555a88 100644 (file)
@@ -9,7 +9,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  7,0,2,0\r
+FILEVERSION  7,0,5,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -18,9 +18,9 @@ BEGIN
       VALUE "CompanyName",  "Raw Material Software Limited\0"\r
       VALUE "LegalCopyright",  "Copyright (c) 2020 - Raw Material Software Limited\0"\r
       VALUE "FileDescription",  "DemoRunner\0"\r
-      VALUE "FileVersion",  "7.0.2\0"\r
+      VALUE "FileVersion",  "7.0.5\0"\r
       VALUE "ProductName",  "DemoRunner\0"\r
-      VALUE "ProductVersion",  "7.0.2\0"\r
+      VALUE "ProductVersion",  "7.0.5\0"\r
     END\r
   END\r
 \r
index 7028be67db1445e5c60da4ef1dc3e3f0cc6cf73e..678c53488c60e3c2624e0307c78881fe951e2da5 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_box2d=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_USE_MP3AUDIOFORMAT=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_USE_CAMERA=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DEMO_RUNNER=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\DemoRunner.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 5a4173514606f47b39ef7772e9bce5ea18751c89..c430519c950a000754af9b773edc5e1d2d9a32a6 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <Filter>JUCE Modules\juce_analytics</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 3adeec39e7b6582f0829b4c72ce51141ad786795..d1e516af447a694ed9b3cef6d90f71c687555a88 100644 (file)
@@ -9,7 +9,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  7,0,2,0\r
+FILEVERSION  7,0,5,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -18,9 +18,9 @@ BEGIN
       VALUE "CompanyName",  "Raw Material Software Limited\0"\r
       VALUE "LegalCopyright",  "Copyright (c) 2020 - Raw Material Software Limited\0"\r
       VALUE "FileDescription",  "DemoRunner\0"\r
-      VALUE "FileVersion",  "7.0.2\0"\r
+      VALUE "FileVersion",  "7.0.5\0"\r
       VALUE "ProductName",  "DemoRunner\0"\r
-      VALUE "ProductVersion",  "7.0.2\0"\r
+      VALUE "ProductVersion",  "7.0.5\0"\r
     END\r
   END\r
 \r
index 8fe50429873fe55b25e0aaaa3f0e0cbe0f7ddb10..1e9d52e0a4cc03bfb636a357073e75b92b07de37 100644 (file)
                07EA85D22270E8EA13CA0BBE /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_ENABLE_OBJC_WEAK = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+                               IPHONEOS_DEPLOYMENT_TARGET = 11.0;
                                PRODUCT_NAME = "DemoRunner";
                                SDKROOT = iphoneos;
                                TARGETED_DEVICE_FAMILY = "1,2";
                69330F27DD2C71609336C7D2 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
                                CODE_SIGN_ENTITLEMENTS = "App.entitlements";
                                        "JUCE_CONTENT_SHARING=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_analytics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_DEMO_RUNNER=1",
                                        "JUCE_UNIT_TESTS=1",
                                        "JUCER_XCODE_IPHONE_5BC26AE3=1",
-                                       "JUCE_APP_VERSION=7.0.2",
-                                       "JUCE_APP_VERSION_HEX=0x70002",
+                                       "JUCE_APP_VERSION=7.0.5",
+                                       "JUCE_APP_VERSION_HEX=0x70005",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                B18D059E5616FA729F764229 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
                                CODE_SIGN_ENTITLEMENTS = "App.entitlements";
                                        "JUCE_CONTENT_SHARING=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_analytics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_DEMO_RUNNER=1",
                                        "JUCE_UNIT_TESTS=1",
                                        "JUCER_XCODE_IPHONE_5BC26AE3=1",
-                                       "JUCE_APP_VERSION=7.0.2",
-                                       "JUCE_APP_VERSION_HEX=0x70002",
+                                       "JUCE_APP_VERSION=7.0.5",
+                                       "JUCE_APP_VERSION_HEX=0x70005",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                C01EC82F42B640CA1E54AD53 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_ENABLE_OBJC_WEAK = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+                               IPHONEOS_DEPLOYMENT_TARGET = 11.0;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "DemoRunner";
                                SDKROOT = iphoneos;
index 1e2540691bd808be6920585fc4de477c03b7b880..287e00744135791c3b5a7284d6dbcefae1f290f9 100644 (file)
@@ -30,9 +30,9 @@
     <key>CFBundleSignature</key>\r
     <string>????</string>\r
     <key>CFBundleShortVersionString</key>\r
-    <string>7.0.2</string>\r
+    <string>7.0.5</string>\r
     <key>CFBundleVersion</key>\r
-    <string>7.0.2</string>\r
+    <string>7.0.5</string>\r
     <key>NSHumanReadableCopyright</key>\r
     <string>Copyright (c) 2020 - Raw Material Software Limited</string>\r
     <key>NSHighResolutionCapable</key>\r
index 7bb3ab6c4715d253d0eb5e8e949f18707f7be817..7e9e10ddbb2fc40acdfc164ec1fef0b3f60da6b4 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
 <JUCERPROJECT name="DemoRunner" projectType="guiapp" defines="JUCE_DEMO_RUNNER=1&#10;JUCE_UNIT_TESTS=1"\r
-              bundleIdentifier="com.rmsl.jucedemorunner" version="7.0.2" companyName="Raw Material Software Limited"\r
+              bundleIdentifier="com.rmsl.jucedemorunner" version="7.0.5" companyName="Raw Material Software Limited"\r
               companyCopyright="Copyright (c) 2020 - Raw Material Software Limited"\r
               companyWebsite="https://www.juce.com/" companyEmail="info@juce.com"\r
               id="yj7xMM" reportAppUsage="0" useAppConfig="0" addUsingNamespaceToJuceHeader="1"\r
       </MODULEPATHS>\r
     </LINUX_MAKE>\r
     <ANDROIDSTUDIO targetFolder="Builds/Android" androidMinimumSDK="23" microphonePermissionNeeded="1"\r
-                   androidBluetoothNeeded="1" androidExternalReadNeeded="1" androidExternalWriteNeeded="1"\r
-                   androidEnableContentSharing="1" androidExtraAssetsFolder="../Assets"\r
-                   smallIcon="YyqWd2" bigIcon="YyqWd2" cameraPermissionNeeded="1"\r
-                   androidTargetSDK="31">\r
+                   androidExternalWriteNeeded="1" androidEnableContentSharing="1"\r
+                   androidExtraAssetsFolder="../Assets" smallIcon="YyqWd2" bigIcon="YyqWd2"\r
+                   cameraPermissionNeeded="1" androidReadMediaAudioPermission="1"\r
+                   androidReadMediaImagesPermission="1" androidReadMediaVideoPermission="1"\r
+                   androidBluetoothScanNeeded="1" androidBluetoothAdvertiseNeeded="1"\r
+                   androidBluetoothConnectNeeded="1">\r
       <CONFIGURATIONS>\r
         <CONFIGURATION isDebug="1" name="Debug" recommendedWarnings="LLVM"/>\r
         <CONFIGURATION isDebug="0" name="Release" recommendedWarnings="LLVM"/>\r
index 7b3ed11a3eb4cd2531ea5a70ddf60bd44964131a..3ac4001449eed4d0c4e7c79cec8bbb4ba20cdde5 100644 (file)
@@ -54,7 +54,7 @@ namespace ProjectInfo
 {\r
     const char* const  projectName    = "DemoRunner";\r
     const char* const  companyName    = "Raw Material Software Limited";\r
-    const char* const  versionString  = "7.0.2";\r
-    const int          versionNumber  = 0x70002;\r
+    const char* const  versionString  = "7.0.5";\r
+    const int          versionNumber  = 0x70005;\r
 }\r
 #endif\r
index ef0d1f3903fb072df46e10bd97f42ea1aac57a87..8d92e06f10a948ee07c3206b2ec3309400a1e0a7 100644 (file)
@@ -59,7 +59,7 @@ public:
     AnimationAppDemo()\r
     {\r
         setSize (800, 600);\r
-        setFramesPerSecond (60);\r
+        setSynchroniseToVBlank (true);\r
     }\r
 \r
     void update() override\r
index a03c68403edf6327373f6eee9acc9225226704e2..6a112533caa5944d0795b9ef45e43c0ed418dd5c 100644 (file)
@@ -57,7 +57,7 @@ public:
     {\r
         setOpaque (true);\r
         imageList.setDirectory (File::getSpecialLocation (File::userPicturesDirectory), true, true);\r
-        directoryThread.startThread (1);\r
+        directoryThread.startThread (Thread::Priority::background);\r
 \r
         fileTree.setTitle ("Files");\r
         fileTree.addListener (this);\r
index ee5cbd65819cb78f8ec480d2f0060867c28ff560..2fbcc8b1fbddb4318f8a5b6798e3ab5bbca54f76 100644 (file)
@@ -205,7 +205,7 @@ public:
             attributes.reset();\r
             uniforms  .reset();\r
 \r
-            shader.reset (newShader.release());\r
+            shader = std::move (newShader);\r
             shader->use();\r
 \r
             shape     .reset (new Shape());\r
index 3f7d02ed056edc674957c8ac6957b9ed6f5e892e..086f5aa0a11da4d7691467dbd8d0d36b6bb443ba 100644 (file)
@@ -154,7 +154,7 @@ public:
         setOpaque (true);\r
 \r
         movieList.setDirectory (File::getSpecialLocation (File::userMoviesDirectory), true, true);\r
-        directoryThread.startThread (1);\r
+        directoryThread.startThread (Thread::Priority::background);\r
 \r
         fileTree.setTitle ("Files");\r
         fileTree.addListener (this);\r
index 9d59439a03b1a9df6d98bc6904eaa6f9a970577c..17befd7bed2c0cd7c9e0aba1c7c0bf85ea6a91ea 100644 (file)
 \r
 #pragma once\r
 \r
+#include <ARA_Library/Utilities/ARAPitchInterpretation.h>\r
+#include <ARA_Library/Utilities/ARATimelineConversion.h>\r
+\r
+//==============================================================================\r
+class ARADemoPluginAudioModification  : public ARAAudioModification\r
+{\r
+public:\r
+    ARADemoPluginAudioModification (ARAAudioSource* audioSource,\r
+                                    ARA::ARAAudioModificationHostRef hostRef,\r
+                                    const ARAAudioModification* optionalModificationToClone)\r
+        : ARAAudioModification (audioSource, hostRef, optionalModificationToClone)\r
+    {\r
+        if (optionalModificationToClone != nullptr)\r
+            dimmed = static_cast<const ARADemoPluginAudioModification*> (optionalModificationToClone)->dimmed;\r
+    }\r
+\r
+    bool isDimmed() const           { return dimmed; }\r
+    void setDimmed (bool shouldDim) { dimmed = shouldDim; }\r
+\r
+private:\r
+    bool dimmed = false;\r
+};\r
 \r
 //==============================================================================\r
 struct PreviewState\r
@@ -63,7 +85,7 @@ public:
     SharedTimeSliceThread()\r
         : TimeSliceThread (String (JucePlugin_Name) + " ARA Sample Reading Thread")\r
     {\r
-        startThread (7);  // Above default priority so playback is fluent, but below realtime\r
+        startThread (Priority::high);  // Above default priority so playback is fluent, but below realtime\r
     }\r
 };\r
 \r
@@ -95,6 +117,18 @@ private:
     SpinLock processingFlag;\r
 };\r
 \r
+static void crossfade (const float* sourceA,\r
+                       const float* sourceB,\r
+                       float aProportionAtStart,\r
+                       float aProportionAtFinish,\r
+                       float* destinationBuffer,\r
+                       int numSamples)\r
+{\r
+    AudioBuffer<float> destination { &destinationBuffer, 1, numSamples };\r
+    destination.copyFromWithRamp (0, 0, sourceA, numSamples, aProportionAtStart, aProportionAtFinish);\r
+    destination.addFromWithRamp (0, 0, sourceB, numSamples, 1.0f - aProportionAtStart, 1.0f - aProportionAtFinish);\r
+}\r
+\r
 class Looper\r
 {\r
 public:\r
@@ -110,68 +144,83 @@ public:
     void writeInto (AudioBuffer<float>& buffer)\r
     {\r
         if (loopRange.getLength() == 0)\r
+        {\r
             buffer.clear();\r
+            return;\r
+        }\r
 \r
         const auto numChannelsToCopy = std::min (inputBuffer->getNumChannels(), buffer.getNumChannels());\r
+        const auto actualCrossfadeLengthSamples = std::min (loopRange.getLength() / 2, (int64) desiredCrossfadeLengthSamples);\r
 \r
         for (auto samplesCopied = 0; samplesCopied < buffer.getNumSamples();)\r
         {\r
-            const auto numSamplesToCopy =\r
-                std::min (buffer.getNumSamples() - samplesCopied, (int) (loopRange.getEnd() - pos));\r
+            const auto [needsCrossfade, samplePosOfNextCrossfadeTransition] = [&]() -> std::pair<bool, int64>\r
+            {\r
+                if (const auto endOfFadeIn = loopRange.getStart() + actualCrossfadeLengthSamples; pos < endOfFadeIn)\r
+                    return { true, endOfFadeIn };\r
+\r
+                return { false, loopRange.getEnd() - actualCrossfadeLengthSamples };\r
+            }();\r
+\r
+            const auto samplesToNextCrossfadeTransition = samplePosOfNextCrossfadeTransition - pos;\r
+            const auto numSamplesToCopy = std::min (buffer.getNumSamples() - samplesCopied,\r
+                                                    (int) samplesToNextCrossfadeTransition);\r
+\r
+            const auto getFadeInGainAtPos = [this, actualCrossfadeLengthSamples] (auto p)\r
+            {\r
+                return jmap ((float) p, (float) loopRange.getStart(), (float) loopRange.getStart() + (float) actualCrossfadeLengthSamples - 1.0f, 0.0f, 1.0f);\r
+            };\r
 \r
             for (int i = 0; i < numChannelsToCopy; ++i)\r
             {\r
-                buffer.copyFrom (i, samplesCopied, *inputBuffer, i, (int) pos, numSamplesToCopy);\r
+                if (needsCrossfade)\r
+                {\r
+                    const auto overlapStart = loopRange.getEnd() - actualCrossfadeLengthSamples\r
+                                              + (pos - loopRange.getStart());\r
+\r
+                    crossfade (inputBuffer->getReadPointer (i, (int) pos),\r
+                               inputBuffer->getReadPointer (i, (int) overlapStart),\r
+                               getFadeInGainAtPos (pos),\r
+                               getFadeInGainAtPos (pos + numSamplesToCopy),\r
+                               buffer.getWritePointer (i, samplesCopied),\r
+                               numSamplesToCopy);\r
+                }\r
+                else\r
+                {\r
+                    buffer.copyFrom (i, samplesCopied, *inputBuffer, i, (int) pos, numSamplesToCopy);\r
+                }\r
             }\r
 \r
             samplesCopied += numSamplesToCopy;\r
             pos += numSamplesToCopy;\r
 \r
-            jassert (pos <= loopRange.getEnd());\r
+            jassert (pos <= loopRange.getEnd() - actualCrossfadeLengthSamples);\r
 \r
-            if (pos == loopRange.getEnd())\r
+            if (pos == loopRange.getEnd() - actualCrossfadeLengthSamples)\r
                 pos = loopRange.getStart();\r
         }\r
     }\r
 \r
 private:\r
+    static constexpr int desiredCrossfadeLengthSamples = 50;\r
+\r
     const AudioBuffer<float>* inputBuffer;\r
     Range<int64> loopRange;\r
     int64 pos;\r
 };\r
 \r
-class OptionalRange\r
-{\r
-public:\r
-    using Type = Range<int64>;\r
-\r
-    OptionalRange() : valid (false) {}\r
-    explicit OptionalRange (Type valueIn) : valid (true), value (std::move (valueIn)) {}\r
-\r
-    explicit operator bool() const noexcept { return valid; }\r
-\r
-    const auto& operator*() const\r
-    {\r
-        jassert (valid);\r
-        return value;\r
-    }\r
-\r
-private:\r
-    bool valid;\r
-    Type value;\r
-};\r
-\r
 //==============================================================================\r
 // Returns the modified sample range in the output buffer.\r
-inline OptionalRange readPlaybackRangeIntoBuffer (Range<double> playbackRange,\r
-                                                  const ARAPlaybackRegion* playbackRegion,\r
-                                                  AudioBuffer<float>& buffer,\r
-                                                  const std::function<AudioFormatReader* (ARA::PlugIn::AudioSource*)>& getReader)\r
+inline std::optional<Range<int64>> readPlaybackRangeIntoBuffer (Range<double> playbackRange,\r
+                                                                const ARAPlaybackRegion* playbackRegion,\r
+                                                                AudioBuffer<float>& buffer,\r
+                                                                const std::function<AudioFormatReader* (ARAAudioSource*)>& getReader)\r
 {\r
-    const auto rangeInAudioModificationTime = playbackRange.movedToStartAt (playbackRange.getStart()\r
-                                                                            - playbackRegion->getStartInAudioModificationTime());\r
+    const auto rangeInAudioModificationTime = playbackRange - playbackRegion->getStartInPlaybackTime()\r
+                                                            + playbackRegion->getStartInAudioModificationTime();\r
 \r
-    const auto audioSource = playbackRegion->getAudioModification()->getAudioSource();\r
+    const auto audioModification = playbackRegion->getAudioModification<ARADemoPluginAudioModification>();\r
+    const auto audioSource = audioModification->getAudioSource();\r
     const auto audioModificationSampleRate = audioSource->getSampleRate();\r
 \r
     const Range<int64_t> sampleRangeInAudioModification {\r
@@ -181,7 +230,9 @@ inline OptionalRange readPlaybackRangeIntoBuffer (Range<double> playbackRange,
 \r
     const auto inputOffset = jlimit ((int64_t) 0, audioSource->getSampleCount(), sampleRangeInAudioModification.getStart());\r
 \r
-    const auto outputOffset = -std::min (sampleRangeInAudioModification.getStart(), (int64_t) 0);\r
+    // With the output offset it can always be said of the output buffer, that the zeroth element\r
+    // corresponds to beginning of the playbackRange.\r
+    const auto outputOffset = std::max (-sampleRangeInAudioModification.getStart(), (int64_t) 0);\r
 \r
     /* TODO: Handle different AudioSource and playback sample rates.\r
 \r
@@ -203,12 +254,17 @@ inline OptionalRange readPlaybackRangeIntoBuffer (Range<double> playbackRange,
     }();\r
 \r
     if (readLength == 0)\r
-        return OptionalRange { {} };\r
+        return Range<int64>();\r
 \r
     auto* reader = getReader (audioSource);\r
 \r
     if (reader != nullptr && reader->read (&buffer, (int) outputOffset, (int) readLength, inputOffset, true, true))\r
-        return OptionalRange { { outputOffset, readLength } };\r
+    {\r
+        if (audioModification->isDimmed())\r
+            buffer.applyGain ((int) outputOffset, (int) readLength, 0.25f);\r
+\r
+        return Range<int64>::withStartAndLength (outputOffset, readLength);\r
+    }\r
 \r
     return {};\r
 }\r
@@ -363,6 +419,11 @@ public:
                     continue;\r
                 }\r
 \r
+                // Apply dim if enabled\r
+                if (playbackRegion->getAudioModification<ARADemoPluginAudioModification>()->isDimmed())\r
+                    readBuffer.applyGain (startInBuffer, numSamplesToRead, 0.25f);  // dim by about 12 dB\r
+\r
+                // Mix output of all regions\r
                 if (didRenderAnyRegion)\r
                 {\r
                     // Mix local buffer into the output buffer.\r
@@ -400,7 +461,7 @@ private:
     // We're subclassing here only to provide a proper default c'tor for our shared resource\r
 \r
     SharedResourcePointer<SharedTimeSliceThread> sharedTimesliceThread;\r
-    std::map<ARA::PlugIn::AudioSource*, PossiblyBufferedReader> audioSourceReaders;\r
+    std::map<ARAAudioSource*, PossiblyBufferedReader> audioSourceReaders;\r
     bool useBufferedAudioSourceReader = true;\r
     int numChannels = 2;\r
     double sampleRate = 48000.0;\r
@@ -431,7 +492,7 @@ public:
 \r
     void didAddRegionSequence (ARA::PlugIn::RegionSequence* rs) noexcept override\r
     {\r
-        auto* sequence = dynamic_cast<ARARegionSequence*> (rs);\r
+        auto* sequence = static_cast<ARARegionSequence*> (rs);\r
         sequence->addListener (this);\r
         regionSequences.insert (sequence);\r
         asyncConfigCallback.startConfigure();\r
@@ -493,8 +554,21 @@ public:
             if (! locked)\r
                 return true;\r
 \r
+            const auto fadeOutIfNecessary = [this, &buffer]\r
+            {\r
+                if (std::exchange (wasPreviewing, false))\r
+                {\r
+                    previewLooper.writeInto (buffer);\r
+                    const auto fadeOutStart = std::max (0, buffer.getNumSamples() - 50);\r
+                    buffer.applyGainRamp (fadeOutStart, buffer.getNumSamples() - fadeOutStart, 1.0f, 0.0f);\r
+                }\r
+            };\r
+\r
             if (positionInfo.getIsPlaying())\r
+            {\r
+                fadeOutIfNecessary();\r
                 return true;\r
+            }\r
 \r
             if (const auto previewedRegion = previewState->previewedRegion.load())\r
             {\r
@@ -519,8 +593,12 @@ public:
                 if (regionIsAssignedToEditor)\r
                 {\r
                     const auto previewTime = previewState->previewTime.load();\r
+                    const auto previewDimmed = previewedRegion->getAudioModification<ARADemoPluginAudioModification>()\r
+                                                              ->isDimmed();\r
 \r
-                    if (lastPreviewTime != previewTime || lastPlaybackRegion != previewedRegion)\r
+                    if (lastPreviewTime != previewTime\r
+                        || lastPlaybackRegion != previewedRegion\r
+                        || lastPreviewDimmed != previewDimmed)\r
                     {\r
                         Range<double> previewRangeInPlaybackTime { previewTime - 0.25, previewTime + 0.25 };\r
                         previewBuffer->clear();\r
@@ -537,15 +615,26 @@ public:
                         {\r
                             lastPreviewTime = previewTime;\r
                             lastPlaybackRegion = previewedRegion;\r
+                            lastPreviewDimmed = previewDimmed;\r
                             previewLooper = Looper (previewBuffer.get(), *rangeInOutput);\r
                         }\r
                     }\r
                     else\r
                     {\r
                         previewLooper.writeInto (buffer);\r
+\r
+                        if (! std::exchange (wasPreviewing, true))\r
+                        {\r
+                            const auto fadeInLength = std::min (50, buffer.getNumSamples());\r
+                            buffer.applyGainRamp (0, fadeInLength, 0.0f, 1.0f);\r
+                        }\r
                     }\r
                 }\r
             }\r
+            else\r
+            {\r
+                fadeOutIfNecessary();\r
+            }\r
 \r
             return true;\r
         });\r
@@ -576,12 +665,14 @@ private:
     AsyncConfigurationCallback asyncConfigCallback { [this] { configure(); } };\r
     double lastPreviewTime = 0.0;\r
     ARAPlaybackRegion* lastPlaybackRegion = nullptr;\r
+    bool lastPreviewDimmed = false;\r
+    bool wasPreviewing = false;\r
     std::unique_ptr<AudioBuffer<float>> previewBuffer;\r
     Looper previewLooper;\r
 \r
     double sampleRate = 48000.0;\r
     SharedResourcePointer<SharedTimeSliceThread> timeSliceThread;\r
-    std::map<ARA::PlugIn::AudioSource*, std::unique_ptr<BufferingAudioReader>> audioSourceReaders;\r
+    std::map<ARAAudioSource*, std::unique_ptr<BufferingAudioReader>> audioSourceReaders;\r
 \r
     std::set<ARARegionSequence*> regionSequences;\r
 };\r
@@ -595,6 +686,15 @@ public:
     PreviewState previewState;\r
 \r
 protected:\r
+    ARAAudioModification* doCreateAudioModification (ARAAudioSource* audioSource,\r
+                                                     ARA::ARAAudioModificationHostRef hostRef,\r
+                                                     const ARAAudioModification* optionalModificationToClone) noexcept override\r
+    {\r
+        return new ARADemoPluginAudioModification (audioSource,\r
+                                                   hostRef,\r
+                                                   static_cast<const ARADemoPluginAudioModification*> (optionalModificationToClone));\r
+    }\r
+\r
     ARAPlaybackRenderer* doCreatePlaybackRenderer() noexcept override\r
     {\r
         return new PlaybackRenderer (getDocumentController());\r
@@ -608,36 +708,108 @@ protected:
     bool doRestoreObjectsFromStream (ARAInputStream& input,\r
                                      const ARARestoreObjectsFilter* filter) noexcept override\r
     {\r
-        ignoreUnused (input, filter);\r
-        return false;\r
+        // Start reading data from the archive, starting with the number of audio modifications in the archive\r
+        const auto numAudioModifications = input.readInt64();\r
+\r
+        // Loop over stored audio modification data\r
+        for (int64 i = 0; i < numAudioModifications; ++i)\r
+        {\r
+            const auto progressVal = (float) i / (float) numAudioModifications;\r
+            getDocumentController()->getHostArchivingController()->notifyDocumentUnarchivingProgress (progressVal);\r
+\r
+            // Read audio modification persistent ID and analysis result from archive\r
+            const String persistentID = input.readString();\r
+            const bool dimmed = input.readBool();\r
+\r
+            // Find audio modification to restore the state to (drop state if not to be loaded)\r
+            auto audioModification = filter->getAudioModificationToRestoreStateWithID<ARADemoPluginAudioModification> (persistentID.getCharPointer());\r
+\r
+            if (audioModification == nullptr)\r
+                continue;\r
+\r
+            const bool dimChanged = (dimmed != audioModification->isDimmed());\r
+            audioModification->setDimmed (dimmed);\r
+\r
+            // If the dim state changed, send a sample content change notification without notifying the host\r
+            if (dimChanged)\r
+            {\r
+                audioModification->notifyContentChanged (ARAContentUpdateScopes::samplesAreAffected(), false);\r
+\r
+                for (auto playbackRegion : audioModification->getPlaybackRegions())\r
+                    playbackRegion->notifyContentChanged (ARAContentUpdateScopes::samplesAreAffected(), false);\r
+            }\r
+        }\r
+\r
+        getDocumentController()->getHostArchivingController()->notifyDocumentUnarchivingProgress (1.0f);\r
+\r
+        return ! input.failed();\r
     }\r
 \r
     bool doStoreObjectsToStream (ARAOutputStream& output, const ARAStoreObjectsFilter* filter) noexcept override\r
     {\r
-        ignoreUnused (output, filter);\r
-        return false;\r
+        // This example implementation only deals with audio modification states\r
+        const auto& audioModificationsToPersist { filter->getAudioModificationsToStore<ARADemoPluginAudioModification>() };\r
+\r
+        const auto reportProgress = [archivingController = getDocumentController()->getHostArchivingController()] (float p)\r
+        {\r
+            archivingController->notifyDocumentArchivingProgress (p);\r
+        };\r
+\r
+        const ScopeGuard scope { [&reportProgress] { reportProgress (1.0f); } };\r
+\r
+        // Write the number of audio modifications we are persisting\r
+        const auto numAudioModifications = audioModificationsToPersist.size();\r
+\r
+        if (! output.writeInt64 ((int64) numAudioModifications))\r
+            return false;\r
+\r
+        // For each audio modification to persist, persist its ID followed by whether it's dimmed\r
+        for (size_t i = 0; i < numAudioModifications; ++i)\r
+        {\r
+            // Write persistent ID and dim state\r
+            if (! output.writeString (audioModificationsToPersist[i]->getPersistentID()))\r
+                return false;\r
+\r
+            if (! output.writeBool (audioModificationsToPersist[i]->isDimmed()))\r
+                return false;\r
+\r
+            const auto progressVal = (float) i / (float) numAudioModifications;\r
+            reportProgress (progressVal);\r
+        }\r
+\r
+        return true;\r
     }\r
 };\r
 \r
 struct PlayHeadState\r
 {\r
-    void update (AudioPlayHead* aph)\r
+    void update (const Optional<AudioPlayHead::PositionInfo>& info)\r
     {\r
-        const auto info = aph->getPosition();\r
-\r
-        if (info.hasValue() && info->getIsPlaying())\r
+        if (info.hasValue())\r
         {\r
-            isPlaying.store (true);\r
-            timeInSeconds.store (info->getTimeInSeconds().orFallback (0));\r
+            isPlaying.store (info->getIsPlaying(), std::memory_order_relaxed);\r
+            timeInSeconds.store (info->getTimeInSeconds().orFallback (0), std::memory_order_relaxed);\r
+            isLooping.store (info->getIsLooping(), std::memory_order_relaxed);\r
+            const auto loopPoints = info->getLoopPoints();\r
+\r
+            if (loopPoints.hasValue())\r
+            {\r
+                loopPpqStart = loopPoints->ppqStart;\r
+                loopPpqEnd = loopPoints->ppqEnd;\r
+            }\r
         }\r
         else\r
         {\r
-            isPlaying.store (false);\r
+            isPlaying.store (false, std::memory_order_relaxed);\r
+            isLooping.store (false, std::memory_order_relaxed);\r
         }\r
     }\r
 \r
-    std::atomic<bool>   isPlaying     { false };\r
-    std::atomic<double> timeInSeconds { 0.0 };\r
+    std::atomic<bool> isPlaying { false },\r
+                      isLooping { false };\r
+    std::atomic<double> timeInSeconds { 0.0 },\r
+                        loopPpqStart  { 0.0 },\r
+                        loopPpqEnd    { 0.0 };\r
 };\r
 \r
 //==============================================================================\r
@@ -655,13 +827,13 @@ public:
     //==============================================================================\r
     void prepareToPlay (double sampleRate, int samplesPerBlock) override\r
     {\r
-        playHeadState.isPlaying.store (false);\r
+        playHeadState.update (nullopt);\r
         prepareToPlayForARA (sampleRate, samplesPerBlock, getMainBusNumOutputChannels(), getProcessingPrecision());\r
     }\r
 \r
     void releaseResources() override\r
     {\r
-        playHeadState.isPlaying.store (false);\r
+        playHeadState.update (nullopt);\r
         releaseResourcesForARA();\r
     }\r
 \r
@@ -681,7 +853,7 @@ public:
         ScopedNoDenormals noDenormals;\r
 \r
         auto* audioPlayHead = getPlayHead();\r
-        playHeadState.update (audioPlayHead);\r
+        playHeadState.update (audioPlayHead->getPosition());\r
 \r
         if (! processBlockForARA (buffer, isRealtime(), audioPlayHead))\r
             processBlockBypassed (buffer, midiMessages);\r
@@ -693,7 +865,15 @@ public:
     const String getName() const override                             { return "ARAPluginDemo"; }\r
     bool acceptsMidi() const override                                 { return true; }\r
     bool producesMidi() const override                                { return true; }\r
-    double getTailLengthSeconds() const override                      { return 0.0; }\r
+\r
+    double getTailLengthSeconds() const override\r
+    {\r
+        double tail;\r
+        if (getTailLengthSecondsForARA (tail))\r
+            return tail;\r
+\r
+        return 0.0;\r
+    }\r
 \r
     //==============================================================================\r
     int getNumPrograms() override                                     { return 0; }\r
@@ -719,6 +899,340 @@ private:
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ARADemoPluginAudioProcessorImpl)\r
 };\r
 \r
+//==============================================================================\r
+class TimeToViewScaling\r
+{\r
+public:\r
+    class Listener\r
+    {\r
+    public:\r
+        virtual ~Listener() = default;\r
+\r
+        virtual void zoomLevelChanged (double newPixelPerSecond) = 0;\r
+    };\r
+\r
+    void addListener (Listener* l)    { listeners.add (l); }\r
+    void removeListener (Listener* l) { listeners.remove (l); }\r
+\r
+    TimeToViewScaling() = default;\r
+\r
+    void zoom (double factor)\r
+    {\r
+        zoomLevelPixelPerSecond = jlimit (minimumZoom, minimumZoom * 32, zoomLevelPixelPerSecond * factor);\r
+        setZoomLevel (zoomLevelPixelPerSecond);\r
+    }\r
+\r
+    void setZoomLevel (double pixelPerSecond)\r
+    {\r
+        zoomLevelPixelPerSecond = pixelPerSecond;\r
+        listeners.call ([this] (Listener& l) { l.zoomLevelChanged (zoomLevelPixelPerSecond); });\r
+    }\r
+\r
+    int getXForTime (double time) const\r
+    {\r
+        return roundToInt (time * zoomLevelPixelPerSecond);\r
+    }\r
+\r
+    double getTimeForX (int x) const\r
+    {\r
+        return x / zoomLevelPixelPerSecond;\r
+    }\r
+\r
+private:\r
+    static constexpr auto minimumZoom = 10.0;\r
+\r
+    double zoomLevelPixelPerSecond = minimumZoom * 4;\r
+    ListenerList<Listener> listeners;\r
+};\r
+\r
+class RulersView : public Component,\r
+                   public SettableTooltipClient,\r
+                   private Timer,\r
+                   private TimeToViewScaling::Listener,\r
+                   private ARAMusicalContext::Listener\r
+{\r
+public:\r
+    class CycleMarkerComponent : public Component\r
+    {\r
+        void paint (Graphics& g) override\r
+        {\r
+            g.setColour (Colours::yellow.darker (0.2f));\r
+            const auto bounds = getLocalBounds().toFloat();\r
+            g.drawRoundedRectangle (bounds.getX(), bounds.getY(), bounds.getWidth(), bounds.getHeight(), 6.0f, 2.0f);\r
+        }\r
+    };\r
+\r
+    RulersView (PlayHeadState& playHeadStateIn, TimeToViewScaling& timeToViewScalingIn, ARADocument& document)\r
+        : playHeadState (playHeadStateIn), timeToViewScaling (timeToViewScalingIn), araDocument (document)\r
+    {\r
+        timeToViewScaling.addListener (this);\r
+\r
+        addChildComponent (cycleMarker);\r
+        cycleMarker.setInterceptsMouseClicks (false, false);\r
+\r
+        setTooltip ("Double-click to start playback, click to stop playback or to reposition, drag horizontal range to set cycle.");\r
+\r
+        startTimerHz (30);\r
+    }\r
+\r
+    ~RulersView() override\r
+    {\r
+        stopTimer();\r
+\r
+        timeToViewScaling.removeListener (this);\r
+        selectMusicalContext (nullptr);\r
+    }\r
+\r
+    void paint (Graphics& g) override\r
+    {\r
+        auto drawBounds = g.getClipBounds();\r
+        const auto drawStartTime = timeToViewScaling.getTimeForX (drawBounds.getX());\r
+        const auto drawEndTime   = timeToViewScaling.getTimeForX (drawBounds.getRight());\r
+\r
+        const auto bounds = getLocalBounds();\r
+\r
+        g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));\r
+        g.fillRect (bounds);\r
+        g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).contrasting());\r
+        g.drawRect (bounds);\r
+\r
+        const auto rulerHeight = bounds.getHeight() / 3;\r
+        g.drawRect (drawBounds.getX(), rulerHeight, drawBounds.getRight(), rulerHeight);\r
+        g.setFont (Font (12.0f));\r
+\r
+        const int lightLineWidth = 1;\r
+        const int heavyLineWidth = 3;\r
+\r
+        if (selectedMusicalContext != nullptr)\r
+        {\r
+            const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeTempoEntries> tempoReader (selectedMusicalContext);\r
+            const ARA::TempoConverter<decltype (tempoReader)> tempoConverter (tempoReader);\r
+\r
+            // chord ruler: one rect per chord, skipping empty "no chords"\r
+            const auto chordBounds = drawBounds.removeFromTop (rulerHeight);\r
+            const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeSheetChords> chordsReader (selectedMusicalContext);\r
+\r
+            if (tempoReader && chordsReader)\r
+            {\r
+                const ARA::ChordInterpreter interpreter (true);\r
+                for (auto itChord = chordsReader.begin(); itChord != chordsReader.end(); ++itChord)\r
+                {\r
+                    if (interpreter.isNoChord (*itChord))\r
+                        continue;\r
+\r
+                    const auto chordStartTime = (itChord == chordsReader.begin()) ? 0 : tempoConverter.getTimeForQuarter (itChord->position);\r
+\r
+                    if (chordStartTime >= drawEndTime)\r
+                        break;\r
+\r
+                    auto chordRect = chordBounds;\r
+                    chordRect.setLeft (timeToViewScaling.getXForTime (chordStartTime));\r
+\r
+                    if (std::next (itChord) != chordsReader.end())\r
+                    {\r
+                        const auto nextChordStartTime = tempoConverter.getTimeForQuarter (std::next (itChord)->position);\r
+\r
+                        if (nextChordStartTime < drawStartTime)\r
+                            continue;\r
+\r
+                        chordRect.setRight (timeToViewScaling.getXForTime (nextChordStartTime));\r
+                    }\r
+\r
+                    g.drawRect (chordRect);\r
+                    g.drawText (convertARAString (interpreter.getNameForChord (*itChord).c_str()),\r
+                                chordRect.withTrimmedLeft (2),\r
+                                Justification::centredLeft);\r
+                }\r
+            }\r
+\r
+            // beat ruler: evaluates tempo and bar signatures to draw a line for each beat\r
+            const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeBarSignatures> barSignaturesReader (selectedMusicalContext);\r
+\r
+            if (barSignaturesReader)\r
+            {\r
+                const ARA::BarSignaturesConverter<decltype (barSignaturesReader)> barSignaturesConverter (barSignaturesReader);\r
+\r
+                const double beatStart = barSignaturesConverter.getBeatForQuarter (tempoConverter.getQuarterForTime (drawStartTime));\r
+                const double beatEnd   = barSignaturesConverter.getBeatForQuarter (tempoConverter.getQuarterForTime (drawEndTime));\r
+                const int endBeat = roundToInt (std::floor (beatEnd));\r
+                RectangleList<int> rects;\r
+\r
+                for (int beat = roundToInt (std::ceil (beatStart)); beat <= endBeat; ++beat)\r
+                {\r
+                    const auto quarterPos = barSignaturesConverter.getQuarterForBeat (beat);\r
+                    const int x = timeToViewScaling.getXForTime (tempoConverter.getTimeForQuarter (quarterPos));\r
+                    const auto barSignature = barSignaturesConverter.getBarSignatureForQuarter (quarterPos);\r
+                    const int lineWidth = (quarterPos == barSignature.position) ? heavyLineWidth : lightLineWidth;\r
+                    const int beatsSinceBarStart = roundToInt( barSignaturesConverter.getBeatDistanceFromBarStartForQuarter (quarterPos));\r
+                    const int lineHeight = (beatsSinceBarStart == 0) ? rulerHeight : rulerHeight / 2;\r
+                    rects.addWithoutMerging (Rectangle<int> (x - lineWidth / 2, 2 * rulerHeight - lineHeight, lineWidth, lineHeight));\r
+                }\r
+\r
+                g.fillRectList (rects);\r
+            }\r
+        }\r
+\r
+        // time ruler: one tick for each second\r
+        {\r
+            RectangleList<int> rects;\r
+\r
+            for (auto time = std::floor (drawStartTime); time <= drawEndTime; time += 1.0)\r
+            {\r
+                const int lineWidth  = (std::fmod (time, 60.0) <= 0.001) ? heavyLineWidth : lightLineWidth;\r
+                const int lineHeight = (std::fmod (time, 10.0) <= 0.001) ? rulerHeight : rulerHeight / 2;\r
+                rects.addWithoutMerging (Rectangle<int> (timeToViewScaling.getXForTime (time) - lineWidth / 2,\r
+                                                         bounds.getHeight() - lineHeight,\r
+                                                         lineWidth,\r
+                                                         lineHeight));\r
+            }\r
+\r
+            g.fillRectList (rects);\r
+        }\r
+    }\r
+\r
+    void mouseDrag (const MouseEvent& m) override\r
+    {\r
+        isDraggingCycle = true;\r
+\r
+        auto cycleRect = getBounds();\r
+        cycleRect.setLeft  (jmin (m.getMouseDownX(), m.x));\r
+        cycleRect.setRight (jmax (m.getMouseDownX(), m.x));\r
+        cycleMarker.setBounds (cycleRect);\r
+    }\r
+\r
+    void mouseUp (const MouseEvent& m) override\r
+    {\r
+        auto playbackController = araDocument.getDocumentController()->getHostPlaybackController();\r
+\r
+        if (playbackController != nullptr)\r
+        {\r
+            const auto startTime = timeToViewScaling.getTimeForX (jmin (m.getMouseDownX(), m.x));\r
+            const auto endTime   = timeToViewScaling.getTimeForX (jmax (m.getMouseDownX(), m.x));\r
+\r
+            if (playHeadState.isPlaying.load (std::memory_order_relaxed))\r
+                playbackController->requestStopPlayback();\r
+            else\r
+                playbackController->requestSetPlaybackPosition (startTime);\r
+\r
+            if (isDraggingCycle)\r
+                playbackController->requestSetCycleRange (startTime, endTime - startTime);\r
+        }\r
+\r
+        isDraggingCycle = false;\r
+    }\r
+\r
+    void mouseDoubleClick (const MouseEvent&) override\r
+    {\r
+        if (auto* playbackController = araDocument.getDocumentController()->getHostPlaybackController())\r
+        {\r
+            if (! playHeadState.isPlaying.load (std::memory_order_relaxed))\r
+                playbackController->requestStartPlayback();\r
+        }\r
+    }\r
+\r
+    void selectMusicalContext (ARAMusicalContext* newSelectedMusicalContext)\r
+    {\r
+        if (auto* oldSelection = std::exchange (selectedMusicalContext, newSelectedMusicalContext);\r
+            oldSelection != selectedMusicalContext)\r
+        {\r
+            if (oldSelection != nullptr)\r
+                oldSelection->removeListener (this);\r
+\r
+            if (selectedMusicalContext != nullptr)\r
+                selectedMusicalContext->addListener (this);\r
+\r
+            repaint();\r
+        }\r
+    }\r
+\r
+    void zoomLevelChanged (double) override\r
+    {\r
+        repaint();\r
+    }\r
+\r
+    void doUpdateMusicalContextContent (ARAMusicalContext*, ARAContentUpdateScopes) override\r
+    {\r
+        repaint();\r
+    }\r
+\r
+private:\r
+    void updateCyclePosition()\r
+    {\r
+        if (selectedMusicalContext != nullptr)\r
+        {\r
+            const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeTempoEntries> tempoReader (selectedMusicalContext);\r
+            const ARA::TempoConverter<decltype (tempoReader)> tempoConverter (tempoReader);\r
+\r
+            const auto loopStartTime = tempoConverter.getTimeForQuarter (playHeadState.loopPpqStart.load (std::memory_order_relaxed));\r
+            const auto loopEndTime   = tempoConverter.getTimeForQuarter (playHeadState.loopPpqEnd.load   (std::memory_order_relaxed));\r
+\r
+            auto cycleRect = getBounds();\r
+            cycleRect.setLeft  (timeToViewScaling.getXForTime (loopStartTime));\r
+            cycleRect.setRight (timeToViewScaling.getXForTime (loopEndTime));\r
+            cycleMarker.setVisible (true);\r
+            cycleMarker.setBounds (cycleRect);\r
+        }\r
+        else\r
+        {\r
+            cycleMarker.setVisible (false);\r
+        }\r
+    }\r
+\r
+    void timerCallback() override\r
+    {\r
+        if (! isDraggingCycle)\r
+            updateCyclePosition();\r
+    }\r
+\r
+private:\r
+    PlayHeadState& playHeadState;\r
+    TimeToViewScaling& timeToViewScaling;\r
+    ARADocument& araDocument;\r
+    ARAMusicalContext* selectedMusicalContext = nullptr;\r
+    CycleMarkerComponent cycleMarker;\r
+    bool isDraggingCycle = false;\r
+};\r
+\r
+class RulersHeader : public Component\r
+{\r
+public:\r
+    RulersHeader()\r
+    {\r
+        chordsLabel.setText ("Chords", NotificationType::dontSendNotification);\r
+        addAndMakeVisible (chordsLabel);\r
+\r
+        barsLabel.setText ("Bars", NotificationType::dontSendNotification);\r
+        addAndMakeVisible (barsLabel);\r
+\r
+        timeLabel.setText ("Time", NotificationType::dontSendNotification);\r
+        addAndMakeVisible (timeLabel);\r
+    }\r
+\r
+    void resized() override\r
+    {\r
+        auto bounds = getLocalBounds();\r
+        const auto rulerHeight = bounds.getHeight() / 3;\r
+\r
+        for (auto* label : { &chordsLabel, &barsLabel, &timeLabel })\r
+            label->setBounds (bounds.removeFromTop (rulerHeight));\r
+    }\r
+\r
+    void paint (Graphics& g) override\r
+    {\r
+        auto bounds = getLocalBounds();\r
+        const auto rulerHeight = bounds.getHeight() / 3;\r
+        g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));\r
+        g.fillRect (bounds);\r
+        g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).contrasting());\r
+        g.drawRect (bounds);\r
+        bounds.removeFromTop (rulerHeight);\r
+        g.drawRect (bounds.removeFromTop (rulerHeight));\r
+    }\r
+\r
+private:\r
+    Label chordsLabel, barsLabel, timeLabel;\r
+};\r
+\r
 //==============================================================================\r
 struct WaveformCache : private ARAAudioSource::Listener\r
 {\r
@@ -772,21 +1286,37 @@ private:
 };\r
 \r
 class PlaybackRegionView : public Component,\r
-                           public ChangeListener\r
+                           public ChangeListener,\r
+                           public SettableTooltipClient,\r
+                           private ARAAudioSource::Listener,\r
+                           private ARAPlaybackRegion::Listener,\r
+                           private ARAEditorView::Listener\r
 {\r
 public:\r
-    PlaybackRegionView (ARAPlaybackRegion& region, WaveformCache& cache)\r
-        : playbackRegion (region), waveformCache (cache)\r
+    PlaybackRegionView (ARAEditorView& editorView, ARAPlaybackRegion& region, WaveformCache& cache)\r
+        : araEditorView (editorView), playbackRegion (region), waveformCache (cache), previewRegionOverlay (*this)\r
     {\r
         auto* audioSource = playbackRegion.getAudioModification()->getAudioSource();\r
 \r
         waveformCache.getOrCreateThumbnail (audioSource).addChangeListener (this);\r
+\r
+        audioSource->addListener (this);\r
+        playbackRegion.addListener (this);\r
+        araEditorView.addListener (this);\r
+        addAndMakeVisible (previewRegionOverlay);\r
+\r
+        setTooltip ("Double-click to toggle dim state of the region, click and hold to prelisten region near click.");\r
     }\r
 \r
     ~PlaybackRegionView() override\r
     {\r
-        waveformCache.getOrCreateThumbnail (playbackRegion.getAudioModification()->getAudioSource())\r
-            .removeChangeListener (this);\r
+        auto* audioSource = playbackRegion.getAudioModification()->getAudioSource();\r
+\r
+        audioSource->removeListener (this);\r
+        playbackRegion.removeListener (this);\r
+        araEditorView.removeListener (this);\r
+\r
+        waveformCache.getOrCreateThumbnail (audioSource).removeChangeListener (this);\r
     }\r
 \r
     void mouseDown (const MouseEvent& m) override\r
@@ -797,6 +1327,7 @@ public:
         auto& previewState = ARADocumentControllerSpecialisation::getSpecialisedDocumentController<ARADemoPluginDocumentControllerSpecialisation> (playbackRegion.getDocumentController())->previewState;\r
         previewState.previewTime.store (previewTime);\r
         previewState.previewedRegion.store (&playbackRegion);\r
+        previewRegionOverlay.update();\r
     }\r
 \r
     void mouseUp (const MouseEvent&) override\r
@@ -804,6 +1335,19 @@ public:
         auto& previewState = ARADocumentControllerSpecialisation::getSpecialisedDocumentController<ARADemoPluginDocumentControllerSpecialisation> (playbackRegion.getDocumentController())->previewState;\r
         previewState.previewTime.store (0.0);\r
         previewState.previewedRegion.store (nullptr);\r
+        previewRegionOverlay.update();\r
+    }\r
+\r
+    void mouseDoubleClick (const MouseEvent&) override\r
+    {\r
+        // Set the dim flag on our region's audio modification when double-clicked\r
+        auto audioModification = playbackRegion.getAudioModification<ARADemoPluginAudioModification>();\r
+        audioModification->setDimmed (! audioModification->isDimmed());\r
+\r
+        // Send a content change notification for the modification and all associated playback regions\r
+        audioModification->notifyContentChanged (ARAContentUpdateScopes::samplesAreAffected(), true);\r
+        for (auto region : audioModification->getPlaybackRegions())\r
+            region->notifyContentChanged (ARAContentUpdateScopes::samplesAreAffected(), true);\r
     }\r
 \r
     void changeListenerCallback (ChangeBroadcaster*) override\r
@@ -811,17 +1355,69 @@ public:
         repaint();\r
     }\r
 \r
+    void didEnableAudioSourceSamplesAccess (ARAAudioSource*, bool) override\r
+    {\r
+        repaint();\r
+    }\r
+\r
+    void willUpdatePlaybackRegionProperties (ARAPlaybackRegion*,\r
+                                             ARAPlaybackRegion::PropertiesPtr newProperties) override\r
+    {\r
+        if (playbackRegion.getName() != newProperties->name\r
+            || playbackRegion.getColor() != newProperties->color)\r
+        {\r
+            repaint();\r
+        }\r
+    }\r
+\r
+    void didUpdatePlaybackRegionContent (ARAPlaybackRegion*, ARAContentUpdateScopes) override\r
+    {\r
+        repaint();\r
+    }\r
+\r
+    void onNewSelection (const ARAViewSelection& viewSelection) override\r
+    {\r
+        const auto& selectedPlaybackRegions = viewSelection.getPlaybackRegions();\r
+        const bool selected = std::find (selectedPlaybackRegions.begin(), selectedPlaybackRegions.end(), &playbackRegion) != selectedPlaybackRegions.end();\r
+        if (selected != isSelected)\r
+        {\r
+            isSelected = selected;\r
+            repaint();\r
+        }\r
+    }\r
+\r
     void paint (Graphics& g) override\r
     {\r
-        g.fillAll (Colours::white.darker());\r
-        g.setColour (Colours::darkgrey.darker());\r
-        auto& thumbnail = waveformCache.getOrCreateThumbnail (playbackRegion.getAudioModification()->getAudioSource());\r
-        thumbnail.drawChannels (g,\r
-                                getLocalBounds(),\r
-                                playbackRegion.getStartInAudioModificationTime(),\r
-                                playbackRegion.getEndInAudioModificationTime(),\r
-                                1.0f);\r
-        g.setColour (Colours::black);\r
+        g.fillAll (convertOptionalARAColour (playbackRegion.getEffectiveColor(), Colours::black));\r
+\r
+        const auto* audioModification = playbackRegion.getAudioModification<ARADemoPluginAudioModification>();\r
+        g.setColour (audioModification->isDimmed() ? Colours::darkgrey.darker() : Colours::darkgrey.brighter());\r
+\r
+        if (audioModification->getAudioSource()->isSampleAccessEnabled())\r
+        {\r
+            auto& thumbnail = waveformCache.getOrCreateThumbnail (playbackRegion.getAudioModification()->getAudioSource());\r
+            thumbnail.drawChannels (g,\r
+                                    getLocalBounds(),\r
+                                    playbackRegion.getStartInAudioModificationTime(),\r
+                                    playbackRegion.getEndInAudioModificationTime(),\r
+                                    1.0f);\r
+        }\r
+        else\r
+        {\r
+            g.setFont (Font (12.0f));\r
+            g.drawText ("Audio Access Disabled", getLocalBounds(), Justification::centred);\r
+        }\r
+\r
+        g.setColour (Colours::white.withMultipliedAlpha (0.9f));\r
+        g.setFont (Font (12.0f));\r
+        g.drawText (convertOptionalARAString (playbackRegion.getEffectiveName()),\r
+                    getLocalBounds(),\r
+                    Justification::topLeft);\r
+\r
+        if (audioModification->isDimmed())\r
+            g.drawText ("DIMMED", getLocalBounds(), Justification::bottomLeft);\r
+\r
+        g.setColour (isSelected ? Colours::white : Colours::black);\r
         g.drawRect (getLocalBounds());\r
     }\r
 \r
@@ -831,18 +1427,70 @@ public:
     }\r
 \r
 private:\r
+    class PreviewRegionOverlay  : public Component\r
+    {\r
+        static constexpr auto previewLength = 0.5;\r
+\r
+    public:\r
+        PreviewRegionOverlay (PlaybackRegionView& ownerIn) : owner (ownerIn)\r
+        {\r
+        }\r
+\r
+        void update()\r
+        {\r
+            const auto& previewState = owner.getDocumentController()->previewState;\r
+\r
+            if (previewState.previewedRegion.load() == &owner.playbackRegion)\r
+            {\r
+                const auto previewStartTime = previewState.previewTime.load() - owner.playbackRegion.getStartInPlaybackTime();\r
+                const auto pixelPerSecond = owner.getWidth() / owner.playbackRegion.getDurationInPlaybackTime();\r
+\r
+                setBounds (roundToInt ((previewStartTime - previewLength / 2) * pixelPerSecond),\r
+                           0,\r
+                           roundToInt (previewLength * pixelPerSecond),\r
+                           owner.getHeight());\r
+\r
+                setVisible (true);\r
+            }\r
+            else\r
+            {\r
+                setVisible (false);\r
+            }\r
+\r
+            repaint();\r
+        }\r
+\r
+        void paint (Graphics& g) override\r
+        {\r
+            g.setColour (Colours::yellow.withAlpha (0.5f));\r
+            g.fillRect (getLocalBounds());\r
+        }\r
+\r
+    private:\r
+        PlaybackRegionView& owner;\r
+    };\r
+\r
+    ARADemoPluginDocumentControllerSpecialisation* getDocumentController() const\r
+    {\r
+        return ARADocumentControllerSpecialisation::getSpecialisedDocumentController<ARADemoPluginDocumentControllerSpecialisation> (playbackRegion.getDocumentController());\r
+    }\r
+\r
+    ARAEditorView& araEditorView;\r
     ARAPlaybackRegion& playbackRegion;\r
     WaveformCache& waveformCache;\r
+    PreviewRegionOverlay previewRegionOverlay;\r
+    bool isSelected = false;\r
 };\r
 \r
 class RegionSequenceView : public Component,\r
-                           public ARARegionSequence::Listener,\r
                            public ChangeBroadcaster,\r
+                           private TimeToViewScaling::Listener,\r
+                           private ARARegionSequence::Listener,\r
                            private ARAPlaybackRegion::Listener\r
 {\r
 public:\r
-    RegionSequenceView (ARARegionSequence& rs, WaveformCache& cache, double pixelPerSec)\r
-        : regionSequence (rs), waveformCache (cache), zoomLevelPixelPerSecond (pixelPerSec)\r
+    RegionSequenceView (ARAEditorView& editorView, TimeToViewScaling& scaling, ARARegionSequence& rs, WaveformCache& cache)\r
+        : araEditorView (editorView), timeToViewScaling (scaling), regionSequence (rs), waveformCache (cache)\r
     {\r
         regionSequence.addListener (this);\r
 \r
@@ -850,10 +1498,14 @@ public:
             createAndAddPlaybackRegionView (playbackRegion);\r
 \r
         updatePlaybackDuration();\r
+\r
+        timeToViewScaling.addListener (this);\r
     }\r
 \r
     ~RegionSequenceView() override\r
     {\r
+        timeToViewScaling.removeListener (this);\r
+\r
         regionSequence.removeListener (this);\r
 \r
         for (const auto& it : playbackRegionViews)\r
@@ -862,6 +1514,16 @@ public:
 \r
     //==============================================================================\r
     // ARA Document change callback overrides\r
+    void willUpdateRegionSequenceProperties (ARARegionSequence*,\r
+                                             ARARegionSequence::PropertiesPtr newProperties) override\r
+    {\r
+        if (regionSequence.getColor() != newProperties->color)\r
+        {\r
+            for (auto& pbr : playbackRegionViews)\r
+                pbr.second->repaint();\r
+        }\r
+    }\r
+\r
     void willRemovePlaybackRegionFromRegionSequence (ARARegionSequence*,\r
                                                      ARAPlaybackRegion* playbackRegion) override\r
     {\r
@@ -885,13 +1547,14 @@ public:
         updatePlaybackDuration();\r
     }\r
 \r
-    void willUpdatePlaybackRegionProperties (ARAPlaybackRegion*, ARAPlaybackRegion::PropertiesPtr) override\r
+    void didUpdatePlaybackRegionProperties (ARAPlaybackRegion*) override\r
     {\r
+        updatePlaybackDuration();\r
     }\r
 \r
-    void didUpdatePlaybackRegionProperties (ARAPlaybackRegion*) override\r
+    void zoomLevelChanged (double) override\r
     {\r
-        updatePlaybackDuration();\r
+        resized();\r
     }\r
 \r
     void resized() override\r
@@ -901,8 +1564,8 @@ public:
             const auto playbackRegion = pbr.first;\r
             pbr.second->setBounds (\r
                 getLocalBounds()\r
-                    .withTrimmedLeft (roundToInt (playbackRegion->getStartInPlaybackTime() * zoomLevelPixelPerSecond))\r
-                    .withWidth (roundToInt (playbackRegion->getDurationInPlaybackTime() * zoomLevelPixelPerSecond)));\r
+                    .withTrimmedLeft (timeToViewScaling.getXForTime (playbackRegion->getStartInPlaybackTime()))\r
+                    .withWidth (timeToViewScaling.getXForTime (playbackRegion->getDurationInPlaybackTime())));\r
         }\r
     }\r
 \r
@@ -911,16 +1574,12 @@ public:
         return playbackDuration;\r
     }\r
 \r
-    void setZoomLevel (double pixelPerSecond)\r
-    {\r
-        zoomLevelPixelPerSecond = pixelPerSecond;\r
-        resized();\r
-    }\r
-\r
 private:\r
     void createAndAddPlaybackRegionView (ARAPlaybackRegion* playbackRegion)\r
     {\r
-        playbackRegionViews[playbackRegion] = std::make_unique<PlaybackRegionView> (*playbackRegion, waveformCache);\r
+        playbackRegionViews[playbackRegion] = std::make_unique<PlaybackRegionView> (araEditorView,\r
+                                                                                    *playbackRegion,\r
+                                                                                    waveformCache);\r
         playbackRegion->addListener (this);\r
         addAndMakeVisible (*playbackRegionViews[playbackRegion]);\r
     }\r
@@ -938,11 +1597,12 @@ private:
         sendChangeMessage();\r
     }\r
 \r
+    ARAEditorView& araEditorView;\r
+    TimeToViewScaling& timeToViewScaling;\r
     ARARegionSequence& regionSequence;\r
     WaveformCache& waveformCache;\r
     std::unordered_map<ARAPlaybackRegion*, std::unique_ptr<PlaybackRegionView>> playbackRegionViews;\r
     double playbackDuration = 0.0;\r
-    double zoomLevelPixelPerSecond;\r
 };\r
 \r
 class ZoomControls : public Component\r
@@ -972,14 +1632,132 @@ private:
     TextButton zoomInButton { "+" }, zoomOutButton { "-" };\r
 };\r
 \r
-class TrackHeader : public Component\r
+class PlayheadPositionLabel : public Label,\r
+                              private Timer\r
 {\r
 public:\r
-    explicit TrackHeader (const ARARegionSequence& regionSequenceIn) : regionSequence (regionSequenceIn)\r
+    PlayheadPositionLabel (PlayHeadState& playHeadStateIn)\r
+        : playHeadState (playHeadStateIn)\r
     {\r
-        update();\r
+        startTimerHz (30);\r
+    }\r
+\r
+    ~PlayheadPositionLabel() override\r
+    {\r
+        stopTimer();\r
+    }\r
+\r
+    void selectMusicalContext (ARAMusicalContext* newSelectedMusicalContext)\r
+    {\r
+        selectedMusicalContext = newSelectedMusicalContext;\r
+    }\r
+\r
+private:\r
+    void timerCallback() override\r
+    {\r
+        const auto timePosition = playHeadState.timeInSeconds.load (std::memory_order_relaxed);\r
+\r
+        auto text = timeToTimecodeString (timePosition);\r
+\r
+        if (playHeadState.isPlaying.load (std::memory_order_relaxed))\r
+            text += " (playing)";\r
+        else\r
+            text += " (stopped)";\r
+\r
+        if (selectedMusicalContext != nullptr)\r
+        {\r
+            const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeTempoEntries> tempoReader (selectedMusicalContext);\r
+            const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeBarSignatures> barSignaturesReader (selectedMusicalContext);\r
+\r
+            if (tempoReader && barSignaturesReader)\r
+            {\r
+                const ARA::TempoConverter<decltype (tempoReader)> tempoConverter (tempoReader);\r
+                const ARA::BarSignaturesConverter<decltype (barSignaturesReader)> barSignaturesConverter (barSignaturesReader);\r
+                const auto quarterPosition = tempoConverter.getQuarterForTime (timePosition);\r
+                const auto barIndex = barSignaturesConverter.getBarIndexForQuarter (quarterPosition);\r
+                const auto beatDistance = barSignaturesConverter.getBeatDistanceFromBarStartForQuarter (quarterPosition);\r
+                const auto quartersPerBeat = 4.0 / (double) barSignaturesConverter.getBarSignatureForQuarter (quarterPosition).denominator;\r
+                const auto beatIndex = (int) beatDistance;\r
+                const auto tickIndex = juce::roundToInt ((beatDistance - beatIndex) * quartersPerBeat * 960.0);\r
+\r
+                text += newLine;\r
+                text += String::formatted ("bar %d | beat %d | tick %03d", (barIndex >= 0) ? barIndex + 1 : barIndex, beatIndex + 1, tickIndex + 1);\r
+                text += "  -  ";\r
+\r
+                const ARA::PlugIn::HostContentReader<ARA::kARAContentTypeSheetChords> chordsReader (selectedMusicalContext);\r
+\r
+                if (chordsReader && chordsReader.getEventCount() > 0)\r
+                {\r
+                    const auto begin = chordsReader.begin();\r
+                    const auto end = chordsReader.end();\r
+                    auto it = begin;\r
+\r
+                    while (it != end && it->position <= quarterPosition)\r
+                        ++it;\r
+\r
+                    if (it != begin)\r
+                        --it;\r
+\r
+                    const ARA::ChordInterpreter interpreter (true);\r
+                    text += "chord ";\r
+                    text += String (interpreter.getNameForChord (*it));\r
+                }\r
+                else\r
+                {\r
+                    text += "(no chords provided)";\r
+                }\r
+            }\r
+        }\r
+\r
+        setText (text, NotificationType::dontSendNotification);\r
+    }\r
+\r
+    // Copied from AudioPluginDemo.h: quick-and-dirty function to format a timecode string\r
+    static String timeToTimecodeString (double seconds)\r
+    {\r
+        auto millisecs = roundToInt (seconds * 1000.0);\r
+        auto absMillisecs = std::abs (millisecs);\r
+\r
+        return String::formatted ("%02d:%02d:%02d.%03d",\r
+                                  millisecs / 3600000,\r
+                                  (absMillisecs / 60000) % 60,\r
+                                  (absMillisecs / 1000)  % 60,\r
+                                  absMillisecs % 1000);\r
+    }\r
+\r
+    PlayHeadState& playHeadState;\r
+    ARAMusicalContext* selectedMusicalContext = nullptr;\r
+};\r
+\r
+class TrackHeader : public Component,\r
+                    private ARARegionSequence::Listener,\r
+                    private ARAEditorView::Listener\r
+{\r
+public:\r
+    TrackHeader (ARAEditorView& editorView, ARARegionSequence& regionSequenceIn)\r
+        : araEditorView (editorView), regionSequence (regionSequenceIn)\r
+    {\r
+        updateTrackName (regionSequence.getName());\r
+        onNewSelection (araEditorView.getViewSelection());\r
 \r
         addAndMakeVisible (trackNameLabel);\r
+\r
+        regionSequence.addListener (this);\r
+        araEditorView.addListener (this);\r
+    }\r
+\r
+    ~TrackHeader() override\r
+    {\r
+        araEditorView.removeListener (this);\r
+        regionSequence.removeListener (this);\r
+    }\r
+\r
+    void willUpdateRegionSequenceProperties (ARARegionSequence*, ARARegionSequence::PropertiesPtr newProperties) override\r
+    {\r
+        if (regionSequence.getName() != newProperties->name)\r
+            updateTrackName (newProperties->name);\r
+        if (regionSequence.getColor() != newProperties->color)\r
+            repaint();\r
     }\r
 \r
     void resized() override\r
@@ -989,30 +1767,43 @@ public:
 \r
     void paint (Graphics& g) override\r
     {\r
-        g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId));\r
-        g.fillRoundedRectangle (getLocalBounds().reduced (2).toType<float>(), 6.0f);\r
-        g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).contrasting());\r
-        g.drawRoundedRectangle (getLocalBounds().reduced (2).toType<float>(), 6.0f, 1.0f);\r
+        const auto backgroundColour = getLookAndFeel().findColour (ResizableWindow::backgroundColourId);\r
+        g.setColour (isSelected ? backgroundColour.brighter() : backgroundColour);\r
+        g.fillRoundedRectangle (getLocalBounds().reduced (2).toFloat(), 6.0f);\r
+        g.setColour (backgroundColour.contrasting());\r
+        g.drawRoundedRectangle (getLocalBounds().reduced (2).toFloat(), 6.0f, 1.0f);\r
+\r
+        if (auto colour = regionSequence.getColor())\r
+        {\r
+            g.setColour (convertARAColour (colour));\r
+            g.fillRect (getLocalBounds().removeFromTop (16).reduced (6));\r
+            g.fillRect (getLocalBounds().removeFromBottom (16).reduced (6));\r
+        }\r
     }\r
 \r
-private:\r
-    void update()\r
+    void onNewSelection (const ARAViewSelection& viewSelection) override\r
     {\r
-        const auto getWithDefaultValue =\r
-            [] (const ARA::PlugIn::OptionalProperty<ARA::ARAUtf8String>& optional, String defaultValue)\r
-        {\r
-            if (const ARA::ARAUtf8String value = optional)\r
-                return String (value);\r
+        const auto& selectedRegionSequences = viewSelection.getRegionSequences();\r
+        const bool selected = std::find (selectedRegionSequences.begin(), selectedRegionSequences.end(), &regionSequence) != selectedRegionSequences.end();\r
 \r
-            return defaultValue;\r
-        };\r
+        if (selected != isSelected)\r
+        {\r
+            isSelected = selected;\r
+            repaint();\r
+        }\r
+    }\r
 \r
-        trackNameLabel.setText (getWithDefaultValue (regionSequence.getName(), "No track name"),\r
+private:\r
+    void updateTrackName (ARA::ARAUtf8String optionalName)\r
+    {\r
+        trackNameLabel.setText (optionalName ? optionalName : "No track name",\r
                                 NotificationType::dontSendNotification);\r
     }\r
 \r
-    const ARARegionSequence& regionSequence;\r
+    ARAEditorView& araEditorView;\r
+    ARARegionSequence& regionSequence;\r
     Label trackNameLabel;\r
+    bool isSelected = false;\r
 };\r
 \r
 constexpr auto trackHeight = 60;\r
@@ -1030,18 +1821,6 @@ public:
             component->resized();\r
         }\r
     }\r
-\r
-    void setOverlayComponent (Component* component)\r
-    {\r
-        if (overlayComponent != nullptr && overlayComponent != component)\r
-            removeChildComponent (overlayComponent);\r
-\r
-        addChildComponent (component);\r
-        overlayComponent = component;\r
-    }\r
-\r
-private:\r
-    Component* overlayComponent = nullptr;\r
 };\r
 \r
 class VerticalLayoutViewport : public Viewport\r
@@ -1069,48 +1848,74 @@ private:
 };\r
 \r
 class OverlayComponent : public Component,\r
-                         private Timer\r
+                         private Timer,\r
+                         private TimeToViewScaling::Listener\r
 {\r
 public:\r
     class PlayheadMarkerComponent : public Component\r
     {\r
-        void paint (Graphics& g) override { g.fillAll (juce::Colours::yellow.darker (0.2f)); }\r
+        void paint (Graphics& g) override { g.fillAll (Colours::yellow.darker (0.2f)); }\r
     };\r
 \r
-    OverlayComponent (PlayHeadState& playHeadStateIn)\r
-        : playHeadState (&playHeadStateIn)\r
+    OverlayComponent (PlayHeadState& playHeadStateIn, TimeToViewScaling& timeToViewScalingIn)\r
+        : playHeadState (playHeadStateIn), timeToViewScaling (timeToViewScalingIn)\r
     {\r
         addChildComponent (playheadMarker);\r
         setInterceptsMouseClicks (false, false);\r
         startTimerHz (30);\r
+\r
+        timeToViewScaling.addListener (this);\r
     }\r
 \r
     ~OverlayComponent() override\r
     {\r
+        timeToViewScaling.removeListener (this);\r
+\r
         stopTimer();\r
     }\r
 \r
     void resized() override\r
     {\r
-        doResize();\r
+        updatePlayHeadPosition();\r
     }\r
 \r
-    void setZoomLevel (double pixelPerSecondIn)\r
+    void setHorizontalOffset (int offset)\r
     {\r
-        pixelPerSecond = pixelPerSecondIn;\r
+        horizontalOffset = offset;\r
     }\r
 \r
-    void setHorizontalOffset (int offset)\r
+    void setSelectedTimeRange (std::optional<ARA::ARAContentTimeRange> timeRange)\r
     {\r
-        horizontalOffset = offset;\r
+        selectedTimeRange = timeRange;\r
+        repaint();\r
+    }\r
+\r
+    void zoomLevelChanged (double) override\r
+    {\r
+        updatePlayHeadPosition();\r
+        repaint();\r
+    }\r
+\r
+    void paint (Graphics& g) override\r
+    {\r
+        if (selectedTimeRange)\r
+        {\r
+            auto bounds = getLocalBounds();\r
+            bounds.setLeft (timeToViewScaling.getXForTime (selectedTimeRange->start));\r
+            bounds.setRight (timeToViewScaling.getXForTime (selectedTimeRange->start + selectedTimeRange->duration));\r
+            g.setColour (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).brighter().withAlpha (0.3f));\r
+            g.fillRect (bounds);\r
+            g.setColour (Colours::whitesmoke.withAlpha (0.5f));\r
+            g.drawRect (bounds);\r
+        }\r
     }\r
 \r
 private:\r
-    void doResize()\r
+    void updatePlayHeadPosition()\r
     {\r
-        if (playHeadState->isPlaying.load())\r
+        if (playHeadState.isPlaying.load (std::memory_order_relaxed))\r
         {\r
-            const auto markerX = playHeadState->timeInSeconds.load() * pixelPerSecond;\r
+            const auto markerX = timeToViewScaling.getXForTime (playHeadState.timeInSeconds.load (std::memory_order_relaxed));\r
             const auto playheadLine = getLocalBounds().withTrimmedLeft ((int) (markerX - markerWidth / 2.0) - horizontalOffset)\r
                                                       .removeFromLeft ((int) markerWidth);\r
             playheadMarker.setVisible (true);\r
@@ -1124,28 +1929,38 @@ private:
 \r
     void timerCallback() override\r
     {\r
-        doResize();\r
+        updatePlayHeadPosition();\r
     }\r
 \r
     static constexpr double markerWidth = 2.0;\r
 \r
-    PlayHeadState* playHeadState;\r
-    double pixelPerSecond = 1.0;\r
+    PlayHeadState& playHeadState;\r
+    TimeToViewScaling& timeToViewScaling;\r
     int horizontalOffset = 0;\r
+    std::optional<ARA::ARAContentTimeRange> selectedTimeRange;\r
     PlayheadMarkerComponent playheadMarker;\r
 };\r
 \r
 class DocumentView  : public Component,\r
                       public ChangeListener,\r
+                      public ARAMusicalContext::Listener,\r
                       private ARADocument::Listener,\r
                       private ARAEditorView::Listener\r
 {\r
 public:\r
-    explicit DocumentView (ARADocument& document, PlayHeadState& playHeadState)\r
-        : araDocument (document),\r
-          overlay (playHeadState)\r
+    DocumentView (ARAEditorView& editorView, PlayHeadState& playHeadState)\r
+        : araEditorView (editorView),\r
+          araDocument (*editorView.getDocumentController()->getDocument<ARADocument>()),\r
+          rulersView (playHeadState, timeToViewScaling, araDocument),\r
+          overlay (playHeadState, timeToViewScaling),\r
+          playheadPositionLabel (playHeadState)\r
     {\r
-        addAndMakeVisible (tracksBackground);\r
+        if (araDocument.getMusicalContexts().size() > 0)\r
+            selectMusicalContext (araDocument.getMusicalContexts().front());\r
+\r
+        addAndMakeVisible (rulersHeader);\r
+\r
+        viewport.content.addAndMakeVisible (rulersView);\r
 \r
         viewport.onVisibleAreaChanged = [this] (const auto& r)\r
         {\r
@@ -1155,25 +1970,40 @@ public:
         };\r
 \r
         addAndMakeVisible (viewport);\r
-\r
-        overlay.setZoomLevel (zoomLevelPixelPerSecond);\r
         addAndMakeVisible (overlay);\r
+        addAndMakeVisible (playheadPositionLabel);\r
 \r
         zoomControls.setZoomInCallback  ([this] { zoom (2.0); });\r
         zoomControls.setZoomOutCallback ([this] { zoom (0.5); });\r
         addAndMakeVisible (zoomControls);\r
 \r
         invalidateRegionSequenceViews();\r
+\r
         araDocument.addListener (this);\r
+        araEditorView.addListener (this);\r
     }\r
 \r
     ~DocumentView() override\r
     {\r
+        araEditorView.removeListener (this);\r
         araDocument.removeListener (this);\r
+        selectMusicalContext (nullptr);\r
     }\r
 \r
     //==============================================================================\r
     // ARADocument::Listener overrides\r
+    void didAddMusicalContextToDocument (ARADocument*, ARAMusicalContext* musicalContext) override\r
+    {\r
+        if (selectedMusicalContext == nullptr)\r
+            selectMusicalContext (musicalContext);\r
+    }\r
+\r
+    void willDestroyMusicalContext (ARAMusicalContext* musicalContext) override\r
+    {\r
+        if (selectedMusicalContext == musicalContext)\r
+            selectMusicalContext (nullptr);\r
+    }\r
+\r
     void didReorderRegionSequencesInDocument (ARADocument*) override\r
     {\r
         invalidateRegionSequenceViews();\r
@@ -1203,12 +2033,32 @@ public:
 \r
     //==============================================================================\r
     // ARAEditorView::Listener overrides\r
-    void onNewSelection (const ARA::PlugIn::ViewSelection&) override\r
+    void onNewSelection (const ARAViewSelection& viewSelection) override\r
     {\r
+        auto getNewSelectedMusicalContext = [&viewSelection]() -> ARAMusicalContext*\r
+        {\r
+            if (! viewSelection.getRegionSequences().empty())\r
+                return viewSelection.getRegionSequences<ARARegionSequence>().front()->getMusicalContext();\r
+            else if (! viewSelection.getPlaybackRegions().empty())\r
+                return viewSelection.getPlaybackRegions<ARAPlaybackRegion>().front()->getRegionSequence()->getMusicalContext();\r
+\r
+            return nullptr;\r
+        };\r
+\r
+        if (auto* newSelectedMusicalContext = getNewSelectedMusicalContext())\r
+            if (newSelectedMusicalContext != selectedMusicalContext)\r
+                selectMusicalContext (newSelectedMusicalContext);\r
+\r
+        if (const auto timeRange = viewSelection.getTimeRange())\r
+            overlay.setSelectedTimeRange (*timeRange);\r
+        else\r
+            overlay.setSelectedTimeRange (std::nullopt);\r
     }\r
 \r
-    void onHideRegionSequences (const std::vector<ARARegionSequence*>&) override\r
+    void onHideRegionSequences (const std::vector<ARARegionSequence*>& regionSequences) override\r
     {\r
+        hiddenRegionSequences = regionSequences;\r
+        invalidateRegionSequenceViews();\r
     }\r
 \r
     //==============================================================================\r
@@ -1220,29 +2070,27 @@ public:
     void resized() override\r
     {\r
         auto bounds = getLocalBounds();\r
-        const auto bottomControlsBounds = bounds.removeFromBottom (40);\r
-        const auto headerBounds = bounds.removeFromLeft (headerWidth).reduced (2);\r
-\r
-        zoomControls.setBounds (bottomControlsBounds);\r
-        layOutVertically (headerBounds, trackHeaders, viewportHeightOffset);\r
-        tracksBackground.setBounds (bounds);\r
-        viewport.setBounds (bounds);\r
-        overlay.setBounds (bounds);\r
-    }\r
 \r
-    //==============================================================================\r
-    void setZoomLevel (double pixelPerSecond)\r
-    {\r
-        zoomLevelPixelPerSecond = pixelPerSecond;\r
+        FlexBox fb;\r
+        fb.justifyContent = FlexBox::JustifyContent::spaceBetween;\r
+        fb.items.add (FlexItem (playheadPositionLabel).withWidth (450.0f).withMinWidth (250.0f));\r
+        fb.items.add (FlexItem (zoomControls).withMinWidth (80.0f));\r
+        fb.performLayout (bounds.removeFromBottom (40));\r
 \r
-        for (const auto& view : regionSequenceViews)\r
-            view.second->setZoomLevel (zoomLevelPixelPerSecond);\r
+        auto headerBounds = bounds.removeFromLeft (headerWidth);\r
+        rulersHeader.setBounds (headerBounds.removeFromTop (trackHeight));\r
+        layOutVertically (headerBounds, trackHeaders, viewportHeightOffset);\r
 \r
-        overlay.setZoomLevel (zoomLevelPixelPerSecond);\r
+        viewport.setBounds (bounds);\r
+        overlay.setBounds (bounds.reduced (1));\r
 \r
-        update();\r
+        const auto width = jmax (timeToViewScaling.getXForTime (timelineLength), viewport.getWidth());\r
+        const auto height = (int) (regionSequenceViews.size() + 1) * trackHeight;\r
+        viewport.content.setSize (width, height);\r
+        viewport.content.resized();\r
     }\r
 \r
+    //==============================================================================\r
     static constexpr int headerWidth = 120;\r
 \r
 private:\r
@@ -1262,10 +2110,26 @@ private:
         ARARegionSequence* sequence;\r
     };\r
 \r
+    void selectMusicalContext (ARAMusicalContext* newSelectedMusicalContext)\r
+    {\r
+        if (auto oldContext = std::exchange (selectedMusicalContext, newSelectedMusicalContext);\r
+            oldContext != selectedMusicalContext)\r
+        {\r
+            if (oldContext != nullptr)\r
+                oldContext->removeListener (this);\r
+\r
+            if (selectedMusicalContext != nullptr)\r
+                selectedMusicalContext->addListener (this);\r
+\r
+            rulersView.selectMusicalContext (selectedMusicalContext);\r
+            playheadPositionLabel.selectMusicalContext (selectedMusicalContext);\r
+        }\r
+    }\r
+\r
     void zoom (double factor)\r
     {\r
-        zoomLevelPixelPerSecond = jlimit (minimumZoom, minimumZoom * 32, zoomLevelPixelPerSecond * factor);\r
-        setZoomLevel (zoomLevelPixelPerSecond);\r
+        timeToViewScaling.zoom (factor);\r
+        update();\r
     }\r
 \r
     template <typename T>\r
@@ -1287,11 +2151,6 @@ private:
         for (const auto& view : regionSequenceViews)\r
             timelineLength = std::max (timelineLength, view.second->getPlaybackDuration());\r
 \r
-        const Rectangle<int> timelineSize (roundToInt (timelineLength * zoomLevelPixelPerSecond),\r
-                                           (int) regionSequenceViews.size() * trackHeight);\r
-        viewport.content.setSize (timelineSize.getWidth(), timelineSize.getHeight());\r
-        viewport.content.resized();\r
-\r
         resized();\r
     }\r
 \r
@@ -1306,14 +2165,14 @@ private:
         auto& regionSequenceView = insertIntoMap (\r
             regionSequenceViews,\r
             RegionSequenceViewKey { regionSequence },\r
-            std::make_unique<RegionSequenceView> (*regionSequence, waveformCache, zoomLevelPixelPerSecond));\r
+            std::make_unique<RegionSequenceView> (araEditorView, timeToViewScaling, *regionSequence, waveformCache));\r
 \r
         regionSequenceView.addChangeListener (this);\r
         viewport.content.addAndMakeVisible (regionSequenceView);\r
 \r
         auto& trackHeader = insertIntoMap (trackHeaders,\r
                                            RegionSequenceViewKey { regionSequence },\r
-                                           std::make_unique<TrackHeader> (*regionSequence));\r
+                                           std::make_unique<TrackHeader> (araEditorView, *regionSequence));\r
 \r
         addAndMakeVisible (trackHeader);\r
     }\r
@@ -1352,9 +2211,8 @@ private:
             trackHeaders.clear();\r
 \r
             for (auto* regionSequence : araDocument.getRegionSequences())\r
-            {\r
-                addTrackViews (regionSequence);\r
-            }\r
+                if (std::find (hiddenRegionSequences.begin(), hiddenRegionSequences.end(), regionSequence) == hiddenRegionSequences.end())\r
+                    addTrackViews (regionSequence);\r
 \r
             update();\r
 \r
@@ -1362,30 +2220,28 @@ private:
         }\r
     }\r
 \r
-    class TracksBackgroundComponent : public Component\r
-    {\r
-        void paint (Graphics& g) override\r
-        {\r
-            g.fillAll (getLookAndFeel().findColour (ResizableWindow::backgroundColourId).brighter());\r
-        }\r
-    };\r
-\r
-    static constexpr auto minimumZoom = 10.0;\r
-    static constexpr auto trackHeight = 60;\r
-\r
+    ARAEditorView& araEditorView;\r
     ARADocument& araDocument;\r
 \r
     bool regionSequenceViewsAreValid = false;\r
-    double timelineLength = 0;\r
-    double zoomLevelPixelPerSecond = minimumZoom * 4;\r
+\r
+    TimeToViewScaling timeToViewScaling;\r
+    double timelineLength = 0.0;\r
+\r
+    ARAMusicalContext* selectedMusicalContext = nullptr;\r
+\r
+    std::vector<ARARegionSequence*> hiddenRegionSequences;\r
 \r
     WaveformCache waveformCache;\r
-    TracksBackgroundComponent tracksBackground;\r
     std::map<RegionSequenceViewKey, std::unique_ptr<TrackHeader>> trackHeaders;\r
     std::map<RegionSequenceViewKey, std::unique_ptr<RegionSequenceView>> regionSequenceViews;\r
+    RulersHeader rulersHeader;\r
+    RulersView rulersView;\r
     VerticalLayoutViewport viewport;\r
     OverlayComponent overlay;\r
     ZoomControls zoomControls;\r
+    PlayheadPositionLabel playheadPositionLabel;\r
+    TooltipWindow tooltip;\r
 \r
     int viewportHeightOffset = 0;\r
 };\r
@@ -1400,17 +2256,14 @@ public:
           AudioProcessorEditorARAExtension (&p)\r
     {\r
         if (auto* editorView = getARAEditorView())\r
-        {\r
-            auto* document = ARADocumentControllerSpecialisation::getSpecialisedDocumentController(editorView->getDocumentController())->getDocument();\r
-            documentView = std::make_unique<DocumentView> (*document, p.playHeadState );\r
-        }\r
+            documentView = std::make_unique<DocumentView> (*editorView, p.playHeadState);\r
 \r
         addAndMakeVisible (documentView.get());\r
 \r
         // ARA requires that plugin editors are resizable to support tight integration\r
         // into the host UI\r
         setResizable (true, false);\r
-        setSize (400, 300);\r
+        setSize (800, 300);\r
     }\r
 \r
     //==============================================================================\r
index a1f205230963980cbd981c8dd6ffe75bc5fc0338..6e5c9c36917a97161d0be62d3b5a1e69f5b8d9cd 100644 (file)
@@ -120,9 +120,8 @@ namespace ID
 \r
 template <typename Func, typename... Items>\r
 constexpr void forEach (Func&& func, Items&&... items)\r
-    noexcept (noexcept (std::initializer_list<int> { (func (std::forward<Items> (items)), 0)... }))\r
 {\r
-    (void) std::initializer_list<int> { ((void) func (std::forward<Items> (items)), 0)... };\r
+    (func (std::forward<Items> (items)), ...);\r
 }\r
 \r
 template <typename... Components>\r
index cedc674d7d73d462db5f7056ffc48926ac3e3215..a481b9e5b19db58ef1440af2c7b09630729d15ef 100644 (file)
@@ -156,7 +156,7 @@ public:
             && 1 <= outputs.size()\r
             && std::all_of (outputs.begin(), outputs.end(), [] (const auto& bus)\r
                {\r
-                   return bus == AudioChannelSet::stereo();\r
+                   return bus.isDisabled() || bus == AudioChannelSet::stereo();\r
                });\r
     }\r
 \r
index 2d2882ff14b316b69a33bb01d4b34c359b74a12f..289e9ff3528cf439286d9a9d94d047e3699b2c4d 100644 (file)
@@ -159,7 +159,7 @@ private:
     template <typename Func>\r
     static std::unique_ptr<Command<Proc>> makeCommand (Func&& func)\r
     {\r
-        using Decayed = typename std::decay<Func>::type;\r
+        using Decayed = std::decay_t<Func>;\r
         return std::make_unique<TemplateCommand<Proc, Decayed>> (std::forward<Func> (func));\r
     }\r
 \r
index 164a98a32545a3c23cd9dc9c45c931f0fa2f33bc..ffc05082726202b7fb32c149d01ec01c536d0fe9 100644 (file)
@@ -192,7 +192,7 @@ private:
     {\r
         purchaseInProgress = false;\r
 \r
-        for (const auto productId : info.purchase.productIds)\r
+        for (const auto& productId : info.purchase.productIds)\r
         {\r
             auto idx = findVoiceIndexFromIdentifier (productId);\r
 \r
@@ -218,9 +218,9 @@ private:
     {\r
         if (success)\r
         {\r
-            for (auto& info : infos)\r
+            for (const auto& info : infos)\r
             {\r
-                for (const auto productId : info.purchase.productIds)\r
+                for (const auto& productId : info.purchase.productIds)\r
                 {\r
                     auto idx = findVoiceIndexFromIdentifier (productId);\r
 \r
@@ -241,7 +241,7 @@ private:
             havePricesBeenFetched = true;\r
             StringArray identifiers;\r
 \r
-            for (auto& voiceProduct : voiceProducts)\r
+            for (const auto& voiceProduct : voiceProducts)\r
                 identifiers.add (voiceProduct.identifier);\r
 \r
             InAppPurchases::getInstance()->getProductsInformation (identifiers);\r
index e2363bad6f0f2492b881787c990cc918493ce3ae..9b329253ff9b837b674eec412db9cb173d144fa6 100644 (file)
@@ -148,9 +148,7 @@ public:
         : BouncingBall (containerComp),\r
           Thread ("JUCE Demo Thread")\r
     {\r
-        // give the threads a random priority, so some will move more\r
-        // smoothly than others..\r
-        startThread (Random::getSystemRandom().nextInt (3) + 3);\r
+        startThread();\r
     }\r
 \r
     ~DemoThread() override\r
index 41f6dfe8be5bf3efee241766407c87c9d00050d4..f4bcddbe8feb1647e7db611e55d8271cd571dd03 100644 (file)
@@ -135,6 +135,7 @@ static String getAllSystemInfo()
       << "Host name:        " << SystemStats::getComputerName()        << newLine\r
       << "Device type:      " << SystemStats::getDeviceDescription()   << newLine\r
       << "Manufacturer:     " << SystemStats::getDeviceManufacturer()  << newLine\r
+      << "Device ID:        " << SystemStats::getUniqueDeviceID()      << newLine\r
       << "User logon name:  " << SystemStats::getLogonName()           << newLine\r
       << "Full user name:   " << SystemStats::getFullUserName()        << newLine\r
       << "User region:      " << SystemStats::getUserRegion()          << newLine\r
index b2721c9cd5c5d44308355c93019e72f995c1a327..be3f6cd76d099dc3171eb5c3cec8f860bd9c2be0 100644 (file)
@@ -1,8 +1,10 @@
-# Automatically generated makefile, created by the Projucer
+# Automatically generated CMakeLists, created by the Projucer
 # Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
 
 cmake_minimum_required(VERSION 3.4.1)
 
+project(juce_jni_project)
+
 set(BINARY_NAME "juce_jni")
 
 set(OBOE_DIR "../../../../../modules/juce_audio_devices/native/oboe")
@@ -23,9 +25,9 @@ include_directories( AFTER
 enable_language(ASM)
 
 if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG")
-    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
+    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70005]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
 elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE")
-    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
+    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70005]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
 else()
     message( FATAL_ERROR "No matching build-configuration found." )
 endif()
@@ -36,6 +38,7 @@ add_library( ${BINARY_NAME}
 
     "../../../Source/Main.cpp"
     "../../../Source/MainComponent.h"
+    "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp"
     "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.h"
@@ -54,6 +57,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPConverters.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPDispatcher.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPFactory.h"
+    "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"
@@ -110,6 +114,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_basics/sources/juce_MemoryAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.h"
+    "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h"
@@ -344,7 +349,6 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
-    "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
@@ -754,6 +758,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h"
     "../../../../../modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h"
+    "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.mm"
@@ -922,6 +927,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/native/juce_mac_Strings.mm"
     "../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
     "../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+    "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
     "../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
     "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
     "../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
@@ -1064,6 +1070,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_data_structures/app_properties/juce_ApplicationProperties.h"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.h"
+    "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.h"
@@ -1519,6 +1526,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAWindowProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_WindowsUIAWrapper.h"
+    "../../../../../modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h"
@@ -1538,6 +1546,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+    "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
     "../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
     "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
     "../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
@@ -1622,6 +1631,8 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.h"
@@ -1666,6 +1677,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"
+    "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.h"
     "../../../../../modules/juce_gui_extra/native/juce_android_PushNotifications.cpp"
     "../../../../../modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"
@@ -1706,6 +1718,7 @@ add_library( ${BINARY_NAME}
 
 set_source_files_properties(
     "../../../Source/MainComponent.h"
+    "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp"
     "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.h"
@@ -1724,6 +1737,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPConverters.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPDispatcher.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPFactory.h"
+    "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"
@@ -1780,6 +1794,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_basics/sources/juce_MemoryAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.h"
+    "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h"
@@ -2014,7 +2029,6 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
-    "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
@@ -2424,6 +2438,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h"
     "../../../../../modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h"
+    "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.mm"
@@ -2592,6 +2607,7 @@ set_source_files_properties(
     "../../../../../modules/juce_core/native/juce_mac_Strings.mm"
     "../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
     "../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+    "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
     "../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
     "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
     "../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
@@ -2734,6 +2750,7 @@ set_source_files_properties(
     "../../../../../modules/juce_data_structures/app_properties/juce_ApplicationProperties.h"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.h"
+    "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.h"
@@ -3189,6 +3206,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAWindowProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_WindowsUIAWrapper.h"
+    "../../../../../modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h"
@@ -3208,6 +3226,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+    "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
     "../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
     "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
     "../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
@@ -3292,6 +3311,8 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.h"
@@ -3336,6 +3357,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"
+    "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.h"
     "../../../../../modules/juce_gui_extra/native/juce_android_PushNotifications.cpp"
     "../../../../../modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"
@@ -3361,14 +3383,12 @@ set_source_files_properties(
     "../../../JuceLibraryCode/JuceHeader.h"
     PROPERTIES HEADER_FILE_ONLY TRUE)
 
-target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" [[-mfpu=neon]] [[-mfloat-abi=hard]] [[-ffast-math]] [[-funroll-loops]] [[--param]] [[max-unroll-times=8]] [[-mhard-float]] [[-D_NDK_MATH_NO_SOFTFP=1]] [[-DJUCE_DISABLE_ASSERTIONS=1]] )
-
 if( JUCE_BUILD_CONFIGURATION MATCHES "DEBUG" )
-    target_compile_options( ${BINARY_NAME} PRIVATE)
+    target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" [[-mfpu=neon]] [[-mfloat-abi=hard]] [[-ffast-math]] [[-funroll-loops]] [[--param]] [[max-unroll-times=8]] [[-mhard-float]] [[-D_NDK_MATH_NO_SOFTFP=1]] [[-DJUCE_DISABLE_ASSERTIONS=1]] )
 endif()
 
 if( JUCE_BUILD_CONFIGURATION MATCHES "RELEASE" )
-    target_compile_options( ${BINARY_NAME} PRIVATE)
+    target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" [[-mfpu=neon]] [[-mfloat-abi=hard]] [[-ffast-math]] [[-funroll-loops]] [[--param]] [[max-unroll-times=8]] [[-mhard-float]] [[-D_NDK_MATH_NO_SOFTFP=1]] [[-DJUCE_DISABLE_ASSERTIONS=1]] )
 endif()
 
 find_library(log "log")
index 74166841d80185ed069948f06e0d5c307ad4c708..d3ce652079345418b5708d3aedd7e216a5323b7a 100644 (file)
@@ -1,7 +1,8 @@
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 30
+    compileSdkVersion 33
+    namespace "com.juce.audioperformancetest"
     externalNativeBuild {
         cmake {
             path "CMakeLists.txt"
@@ -20,10 +21,10 @@ android {
     defaultConfig {
         applicationId "com.juce.audioperformancetest"
         minSdkVersion    23
-        targetSdkVersion 30
+        targetSdkVersion 33
         externalNativeBuild {
             cmake {
-                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF"
+                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=17", "-DCMAKE_CXX_EXTENSIONS=OFF"
             }
         }
     }
@@ -51,21 +52,25 @@ android {
             }
             externalNativeBuild {
                 cmake {
-                    arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-O0", "-DCMAKE_C_FLAGS_DEBUG=-O0"
+                    cFlags    "-O0"
+                    cppFlags  "-O0"
+                    arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG"
                 }
             }
 
             dimension "default"
-       }
+        }
         release_ {
             externalNativeBuild {
                 cmake {
-                    arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-Ofast", "-DCMAKE_C_FLAGS_RELEASE=-Ofast"
+                    cFlags    "-Ofast"
+                    cppFlags  "-Ofast"
+                    arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE"
                 }
             }
 
             dimension "default"
-       }
+        }
     }
 
     variantFilter { variant ->
index de6c234e3acde14ebe095c2319469a5364de81fd..7ab456a921865197f0bce98d486801c98a2e7824 100644 (file)
@@ -1,19 +1,17 @@
 <?xml version="1.0" encoding="utf-8"?>
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0"
-          package="com.juce.audioperformancetest">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0">
   <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"
                     android:xlargeScreens="true"/>
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
-  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
-  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
-  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
-  <uses-permission android:name="android.permission.BLUETOOTH"/>
+  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
   <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <application android:label="@string/app_name" android:name="com.rmsl.juce.JuceApp" android:hardwareAccelerated="false">
-    <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
+    <activity android:name="com.rmsl.juce.JuceActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|navigation"
               android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"
               android:exported="true">
       <intent-filter>
index ee98c096888d52d441152343876cf1066882fe6a..8e2533a6a8e084f3c9a1cd90818d4b330cbde43d 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
        mavenCentral()
    }
    dependencies {
-       classpath 'com.android.tools.build:gradle:7.0.0'
+       classpath 'com.android.tools.build:gradle:7.3.0'
    }
 }
 
index 80082ba57b11f2c7cdc838256a00336bbde9d498..702c227cd3ad7b11fe3589f2c2d97dbf29504ec6 100644 (file)
@@ -1 +1 @@
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
\ No newline at end of file
index 85998ab5935ccf9af49404e4324b3c8311d494a4..d4c14bfe4a18367717b8b02fa94421c3a4c56349 100644 (file)
@@ -39,12 +39,12 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := AudioPerformanceTest
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
@@ -60,12 +60,12 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := AudioPerformanceTest
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
index 4b040710b1ed9a9445abe4610cf69bdc2e4ba22a..133817549367db6f71505cd40c3178697f7e088f 100644 (file)
                19B7C16D592FB25D09022191 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                COPY_PHASE_STRIP = NO;
                                        "DEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                                INFOPLIST_FILE = Info-App.plist;
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_LDFLAGS = "-weak_framework Metal -weak_framework MetalKit";
                                PRODUCT_BUNDLE_IDENTIFIER = com.juce.AudioPerformanceTest;
                B7A6988E30C0A68B01EDC53B /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                DEAD_CODE_STRIPPING = YES;
                                        "NDEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
                                LLVM_LTO = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_LDFLAGS = "-weak_framework Metal -weak_framework MetalKit";
                                PRODUCT_BUNDLE_IDENTIFIER = com.juce.AudioPerformanceTest;
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
index 03a877a6c71eaf48bc2ebd2de55dd52e1f8f2d1f..5ef37cc67b0a6f2612b146503ac4a31c5babd244 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <WarningLevel>Level4</WarningLevel>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\AudioPerformanceTest.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <WarningLevel>Level4</WarningLevel>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\AudioPerformanceTest.exe</OutputFile>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
     <ClCompile Include="..\..\Source\Main.cpp"/>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index d8d4fa21f7144d32dec0aa1ada4163b97bbdacf5..81bc0c6d38b2bfe11e83e10628f5ab72696aa3f1 100644 (file)
     <ClCompile Include="..\..\Source\Main.cpp">\r
       <Filter>AudioPerformanceTest\Source</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index dd6e81db22fb43b6ca7fe50477f1b419171bccf4..841dc5264122162399e6d607eb62e8140a83816e 100644 (file)
                19B7C16D592FB25D09022191 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
                                COMBINE_HIDPI_IMAGES = YES;
                                        "JUCE_CONTENT_SHARING=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                B7A6988E30C0A68B01EDC53B /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
                                COMBINE_HIDPI_IMAGES = YES;
                                        "JUCE_CONTENT_SHARING=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                B907CDF95622107F20CD7617 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_ENABLE_OBJC_WEAK = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+                               IPHONEOS_DEPLOYMENT_TARGET = 11.0;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "AudioPerformanceTest";
                                SDKROOT = iphoneos;
                BF82CBDF63CC37CADC61A511 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_ENABLE_OBJC_WEAK = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+                               IPHONEOS_DEPLOYMENT_TARGET = 11.0;
                                PRODUCT_NAME = "AudioPerformanceTest";
                                SDKROOT = iphoneos;
                                TARGETED_DEVICE_FAMILY = "1,2";
index 292f9efe33090a3c34ff6e2bd0c7dd3ce515301d..c893b151f5e11a6bdc5583cc95318b25c900b916 100644 (file)
@@ -62,7 +62,7 @@ public:
             : DocumentWindow (name, Colours::lightgrey, DocumentWindow::allButtons)\r
         {\r
             setUsingNativeTitleBar (true);\r
-            setContentOwned (createMainContentComponent(), true);\r
+            setContentOwned (new MainContentComponent(), true);\r
             setResizable (false, false);\r
 \r
            #if JUCE_IOS || JUCE_ANDROID\r
index 8785b1cd6da3a0c47a5ec0ac8c9fb83f62fe2b9d..28dbcdbf96a330ce06302c6dbe0d63e980b6132b 100644 (file)
@@ -271,7 +271,3 @@ private:
     //==============================================================================\r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MainContentComponent)\r
 };\r
-\r
-\r
-// (This function is called by the app startup code to create our main component)\r
-Component* createMainContentComponent()     { return new MainContentComponent(); }\r
index 5e1d2c72f5bfe09e2057706b61e6c6cfd5e94500..5e56f67f018bba5c5449b90a97268dff1efb92b6 100644 (file)
       </MODULEPATHS>\r
     </XCODE_IPHONE>\r
     <ANDROIDSTUDIO targetFolder="Builds/Android" androidMinimumSDK="23" androidInternetNeeded="1"\r
-                   microphonePermissionNeeded="1" androidBluetoothNeeded="1" smallIcon="c97aUr"\r
-                   bigIcon="c97aUr" androidExtraAssetsFolder="../../examples/Assets">\r
+                   microphonePermissionNeeded="1" smallIcon="c97aUr" bigIcon="c97aUr"\r
+                   androidExtraAssetsFolder="../../examples/Assets" androidBluetoothScanNeeded="1"\r
+                   androidBluetoothAdvertiseNeeded="1" androidBluetoothConnectNeeded="1">\r
       <CONFIGURATIONS>\r
         <CONFIGURATION name="Debug" isDebug="1" optimisation="1" linkTimeOptimisation="0"\r
                        targetName="Plugin Host" recommendedWarnings="LLVM"/>\r
index ced1756654c80171aa1a1cc0edaf784abfe94215..4e41480c5eae3536beea617862099c163e8ae676 100644 (file)
@@ -1,8 +1,10 @@
-# Automatically generated makefile, created by the Projucer
+# Automatically generated CMakeLists, created by the Projucer
 # Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
 
 cmake_minimum_required(VERSION 3.4.1)
 
+project(juce_jni_project)
+
 set(BINARY_NAME "juce_jni")
 
 set(OBOE_DIR "../../../../../modules/juce_audio_devices/native/oboe")
@@ -32,9 +34,9 @@ include_directories( AFTER
 enable_language(ASM)
 
 if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG")
-    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_WASAPI=1]] [[-DJUCE_DIRECTSOUND=1]] [[-DJUCE_ALSA=1]] [[-DJUCE_USE_FLAC=0]] [[-DJUCE_USE_OGGVORBIS=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_AU=1]] [[-DJUCE_PLUGINHOST_LADSPA=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_USE_CDREADER=0]] [[-DJUCE_USE_CDBURNER=0]] [[-DJUCE_WEB_BROWSER=0]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
+    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70005]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_WASAPI=1]] [[-DJUCE_DIRECTSOUND=1]] [[-DJUCE_ALSA=1]] [[-DJUCE_USE_FLAC=0]] [[-DJUCE_USE_OGGVORBIS=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_AU=1]] [[-DJUCE_PLUGINHOST_LADSPA=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_USE_CDREADER=0]] [[-DJUCE_USE_CDBURNER=0]] [[-DJUCE_WEB_BROWSER=0]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
 elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE")
-    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_WASAPI=1]] [[-DJUCE_DIRECTSOUND=1]] [[-DJUCE_ALSA=1]] [[-DJUCE_USE_FLAC=0]] [[-DJUCE_USE_OGGVORBIS=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_AU=1]] [[-DJUCE_PLUGINHOST_LADSPA=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_USE_CDREADER=0]] [[-DJUCE_USE_CDBURNER=0]] [[-DJUCE_WEB_BROWSER=0]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
+    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70005]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_dsp=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_WASAPI=1]] [[-DJUCE_DIRECTSOUND=1]] [[-DJUCE_ALSA=1]] [[-DJUCE_USE_FLAC=0]] [[-DJUCE_USE_OGGVORBIS=1]] [[-DJUCE_PLUGINHOST_VST3=1]] [[-DJUCE_PLUGINHOST_AU=1]] [[-DJUCE_PLUGINHOST_LADSPA=1]] [[-DJUCE_PLUGINHOST_LV2=1]] [[-DJUCE_USE_CDREADER=0]] [[-DJUCE_USE_CDBURNER=0]] [[-DJUCE_WEB_BROWSER=0]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
     if(NOT (ANDROID_ABI STREQUAL "mips" OR ANDROID_ABI STREQUAL "mips64"))
         set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -flto")
         set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -flto")
@@ -69,6 +71,7 @@ add_library( ${BINARY_NAME}
     "../../../../../examples/Assets/proaudio.path"
     "../../../../../examples/Assets/reverb_ir.wav"
     "../../../../../examples/Assets/singing.ogg"
+    "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp"
     "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.h"
@@ -87,6 +90,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPConverters.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPDispatcher.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPFactory.h"
+    "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"
@@ -143,6 +147,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_basics/sources/juce_MemoryAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.h"
+    "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h"
@@ -377,7 +382,6 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
-    "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
@@ -787,6 +791,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h"
     "../../../../../modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h"
+    "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.mm"
@@ -955,6 +960,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/native/juce_mac_Strings.mm"
     "../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
     "../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+    "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
     "../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
     "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
     "../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
@@ -1112,6 +1118,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_data_structures/app_properties/juce_ApplicationProperties.h"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.h"
+    "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.h"
@@ -1651,6 +1658,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAWindowProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_WindowsUIAWrapper.h"
+    "../../../../../modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h"
@@ -1670,6 +1678,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+    "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
     "../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
     "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
     "../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
@@ -1754,6 +1763,8 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.h"
@@ -1798,6 +1809,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"
+    "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.h"
     "../../../../../modules/juce_gui_extra/native/juce_android_PushNotifications.cpp"
     "../../../../../modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"
@@ -1894,6 +1906,7 @@ set_source_files_properties(
     "../../../../../examples/Assets/proaudio.path"
     "../../../../../examples/Assets/reverb_ir.wav"
     "../../../../../examples/Assets/singing.ogg"
+    "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp"
     "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.h"
@@ -1912,6 +1925,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPConverters.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPDispatcher.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPFactory.h"
+    "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"
@@ -1968,6 +1982,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_basics/sources/juce_MemoryAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.h"
+    "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h"
@@ -2202,7 +2217,6 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
-    "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
@@ -2612,6 +2626,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h"
     "../../../../../modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h"
+    "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.mm"
@@ -2780,6 +2795,7 @@ set_source_files_properties(
     "../../../../../modules/juce_core/native/juce_mac_Strings.mm"
     "../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
     "../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+    "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
     "../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
     "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
     "../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
@@ -2937,6 +2953,7 @@ set_source_files_properties(
     "../../../../../modules/juce_data_structures/app_properties/juce_ApplicationProperties.h"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.h"
+    "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.h"
@@ -3476,6 +3493,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAWindowProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_WindowsUIAWrapper.h"
+    "../../../../../modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h"
@@ -3495,6 +3513,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+    "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
     "../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
     "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
     "../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
@@ -3579,6 +3598,8 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.h"
@@ -3623,6 +3644,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"
+    "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.h"
     "../../../../../modules/juce_gui_extra/native/juce_android_PushNotifications.cpp"
     "../../../../../modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"
@@ -3687,14 +3709,12 @@ set_source_files_properties(
     "../../../JuceLibraryCode/JuceHeader.h"
     PROPERTIES HEADER_FILE_ONLY TRUE)
 
-target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
-
 if( JUCE_BUILD_CONFIGURATION MATCHES "DEBUG" )
-    target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override)
+    target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override "-fsigned-char" )
 endif()
 
 if( JUCE_BUILD_CONFIGURATION MATCHES "RELEASE" )
-    target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override)
+    target_compile_options( ${BINARY_NAME} PRIVATE -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override "-fsigned-char" )
 endif()
 
 find_library(log "log")
index 9904208084d2cd1fe4dbba2de9f7a662c8a2f722..314b1168e81c5102673496e6ff0865db40994421 100644 (file)
@@ -1,7 +1,8 @@
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 30
+    compileSdkVersion 33
+    namespace "com.juce.pluginhost"
     externalNativeBuild {
         cmake {
             path "CMakeLists.txt"
@@ -20,10 +21,10 @@ android {
     defaultConfig {
         applicationId "com.juce.pluginhost"
         minSdkVersion    23
-        targetSdkVersion 30
+        targetSdkVersion 33
         externalNativeBuild {
             cmake {
-                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF"
+                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-23", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=17", "-DCMAKE_CXX_EXTENSIONS=OFF"
             }
         }
     }
@@ -51,21 +52,25 @@ android {
             }
             externalNativeBuild {
                 cmake {
-                    arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-O0", "-DCMAKE_C_FLAGS_DEBUG=-O0"
+                    cFlags    "-O0"
+                    cppFlags  "-O0"
+                    arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG"
                 }
             }
 
             dimension "default"
-       }
+        }
         release_ {
             externalNativeBuild {
                 cmake {
-                    arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-O3", "-DCMAKE_C_FLAGS_RELEASE=-O3"
+                    cFlags    "-O3"
+                    cppFlags  "-O3"
+                    arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE"
                 }
             }
 
             dimension "default"
-       }
+        }
     }
 
     variantFilter { variant ->
index c550fe9dc25edfed529e2eb888e0ad35f85938a4..ed0fcf1b0cd09161392d894e8e499fa55acc816d 100644 (file)
@@ -1,21 +1,26 @@
 <?xml version="1.0" encoding="utf-8"?>
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0"
-          package="com.juce.pluginhost">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0">
   <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"
                     android:xlargeScreens="true"/>
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
-  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
+  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
   <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
   <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
-  <uses-permission android:name="android.permission.BLUETOOTH"/>
+  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30"/>
+  <uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30"/>
+  <uses-permission android:name="android.permission.BLUETOOTH_CONNECT"/>
+  <uses-permission android:name="android.permission.BLUETOOTH_ADVERTISE"/>
+  <uses-permission android:name="android.permission.BLUETOOTH_SCAN"/>
   <uses-permission android:name="android.permission.RECORD_AUDIO"/>
   <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-feature android:glEsVersion="0x00030000" android:required="true"/>
   <application android:label="@string/app_name" android:name="com.rmsl.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
-    <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
+    <activity android:name="com.rmsl.juce.JuceActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|navigation"
               android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"
               android:exported="true">
       <intent-filter>
index dc75464ee9fedd2253da5e0e4b664cadb6fa667d..d706170dc2928f399811a60f294699ef858273f0 100644 (file)
@@ -45,10 +45,12 @@ public:
         clear();\r
     }\r
 \r
-    void audioDeviceIOCallback (const float** inputChannelData, int numInputChannels,\r
-                                float** outputChannelData, int numOutputChannels,\r
-                                int numberOfSamples) override\r
+    void audioDeviceIOCallbackWithContext (const float* const* inputChannelData, int numInputChannels,\r
+                                           float* const* outputChannelData, int numOutputChannels,\r
+                                           int numberOfSamples, const AudioIODeviceCallbackContext& context) override\r
     {\r
+        ignoreUnused (context);\r
+\r
         for (int i = 0; i < numberOfSamples; ++i)\r
         {\r
             float inputSample = 0;\r
index 49ccc278720c9c2fa6dac9af64b2a64556b9c0df..9fa1d5c3a087fcfab074bd9da111855d56406f8a 100644 (file)
@@ -25,7 +25,7 @@ using namespace dsp;
 struct DSPDemoParameterBase    : public ChangeBroadcaster\r
 {\r
     DSPDemoParameterBase (const String& labelName) : name (labelName) {}\r
-    virtual ~DSPDemoParameterBase() {}\r
+    virtual ~DSPDemoParameterBase() = default;\r
 \r
     virtual Component* getComponent() = 0;\r
 \r
@@ -142,7 +142,7 @@ public:
         loadURL (u);\r
     }\r
 \r
-    URL getCurrentURL()    { return currentURL; }\r
+    URL getCurrentURL() const   { return currentURL; }\r
 \r
     void setTransportSource (AudioTransportSource* newSource)\r
     {\r
@@ -189,21 +189,7 @@ private:
 \r
         currentURL = u;\r
 \r
-        InputSource* inputSource = nullptr;\r
-\r
-       #if ! JUCE_IOS\r
-        if (u.isLocalFile())\r
-        {\r
-            inputSource = new FileInputSource (u.getLocalFile());\r
-        }\r
-        else\r
-       #endif\r
-        {\r
-            if (inputSource == nullptr)\r
-                inputSource = new URLInputSource (u);\r
-        }\r
-\r
-        thumbnail.setSource (inputSource);\r
+        thumbnail.setSource (makeInputSource (u).release());\r
 \r
         if (notify)\r
             sendChangeMessage();\r
@@ -407,33 +393,27 @@ public:
         transportSource.reset();\r
         readerSource.reset();\r
 \r
-        AudioFormatReader* newReader = nullptr;\r
+        auto source = makeInputSource (fileToPlay);\r
 \r
-       #if ! JUCE_IOS\r
-        if (fileToPlay.isLocalFile())\r
-        {\r
-            newReader = formatManager.createReaderFor (fileToPlay.getLocalFile());\r
-        }\r
-        else\r
-       #endif\r
-        {\r
-            if (newReader == nullptr)\r
-                newReader = formatManager.createReaderFor (fileToPlay.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)));\r
-        }\r
+        if (source == nullptr)\r
+            return false;\r
 \r
-        reader.reset (newReader);\r
+        auto stream = rawToUniquePtr (source->createInputStream());\r
 \r
-        if (reader.get() != nullptr)\r
-        {\r
-            readerSource.reset (new AudioFormatReaderSource (reader.get(), false));\r
-            readerSource->setLooping (loopState.getValue());\r
+        if (stream == nullptr)\r
+            return false;\r
 \r
-            init();\r
+        reader = rawToUniquePtr (formatManager.createReaderFor (std::move (stream)));\r
 \r
-            return true;\r
-        }\r
+        if (reader == nullptr)\r
+            return false;\r
+\r
+        readerSource.reset (new AudioFormatReaderSource (reader.get(), false));\r
+        readerSource->setLooping (loopState.getValue());\r
+\r
+        init();\r
 \r
-        return false;\r
+        return true;\r
     }\r
 \r
     void togglePlay()\r
@@ -613,7 +593,7 @@ private:
                                       {\r
                                           if (fc.getURLResults().size() > 0)\r
                                           {\r
-                                              auto u = fc.getURLResult();\r
+                                              const auto u = fc.getURLResult();\r
 \r
                                               if (! audioFileReader.loadURL (u))\r
                                                   NativeMessageBox::showAsync (MessageBoxOptions()\r
index bfc1c5d2862ed6d65cd01cf1174df2d1c6173303..ffdfc3631c930a0500cf7f0ef82843cbe47e6316 100644 (file)
@@ -242,4 +242,19 @@ struct SlowerBouncingNumber  : public BouncingNumber
     }\r
 };\r
 \r
+inline std::unique_ptr<InputSource> makeInputSource (const URL& url)\r
+{\r
+   #if JUCE_ANDROID\r
+    if (auto doc = AndroidDocument::fromDocument (url))\r
+        return std::make_unique<AndroidDocumentInputSource> (doc);\r
+   #endif\r
+\r
+   #if ! JUCE_IOS\r
+    if (url.isLocalFile())\r
+        return std::make_unique<FileInputSource> (url.getLocalFile());\r
+   #endif\r
+\r
+    return std::make_unique<URLInputSource> (url);\r
+}\r
+\r
 #endif   // PIP_DEMO_UTILITIES_INCLUDED\r
index ee98c096888d52d441152343876cf1066882fe6a..8e2533a6a8e084f3c9a1cd90818d4b330cbde43d 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
        mavenCentral()
    }
    dependencies {
-       classpath 'com.android.tools.build:gradle:7.0.0'
+       classpath 'com.android.tools.build:gradle:7.3.0'
    }
 }
 
index 80082ba57b11f2c7cdc838256a00336bbde9d498..702c227cd3ad7b11fe3589f2c2d97dbf29504ec6 100644 (file)
@@ -1 +1 @@
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
\ No newline at end of file
index fb0581a48b73ef1d9723eb3646090d8308805d94..6439db8f72104ef1fa46bd2cf62a658aa95395c6 100644 (file)
@@ -39,12 +39,12 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_WASAPI=1" "-DJUCE_DIRECTSOUND=1" "-DJUCE_ALSA=1" "-DJUCE_USE_FLAC=0" "-DJUCE_USE_OGGVORBIS=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_AU=1" "-DJUCE_PLUGINHOST_LADSPA=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_USE_CDREADER=0" "-DJUCE_USE_CDBURNER=0" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_WASAPI=1" "-DJUCE_DIRECTSOUND=1" "-DJUCE_ALSA=1" "-DJUCE_USE_FLAC=0" "-DJUCE_USE_OGGVORBIS=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_AU=1" "-DJUCE_PLUGINHOST_LADSPA=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_USE_CDREADER=0" "-DJUCE_USE_CDBURNER=0" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := AudioPluginHost
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
@@ -60,12 +60,12 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_WASAPI=1" "-DJUCE_DIRECTSOUND=1" "-DJUCE_ALSA=1" "-DJUCE_USE_FLAC=0" "-DJUCE_USE_OGGVORBIS=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_AU=1" "-DJUCE_PLUGINHOST_LADSPA=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_USE_CDREADER=0" "-DJUCE_USE_CDBURNER=0" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_WASAPI=1" "-DJUCE_DIRECTSOUND=1" "-DJUCE_ALSA=1" "-DJUCE_USE_FLAC=0" "-DJUCE_USE_OGGVORBIS=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_AU=1" "-DJUCE_PLUGINHOST_LADSPA=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_USE_CDREADER=0" "-DJUCE_USE_CDBURNER=0" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := AudioPluginHost
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -Os $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
index 7108cf0d0ded81003a12174c5d8d471fd505b67f..0fb33e31d613220da64ea387380af53b20961f0c 100644 (file)
                49453CC5AD9F08D2738464AC /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                DEAD_CODE_STRIPPING = YES;
                                        "NDEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
                                LLVM_LTO = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                C8B793AC1BEFBE7A99BE8352 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                COPY_PHASE_STRIP = NO;
                                        "DEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                                INFOPLIST_FILE = Info-App.plist;
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
index ff0d416bfb80409a82c6a8f72e5129d9a2c04d9a..dd2de8a96733c491d37368cf527d330802042ae0 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
     <ClCompile Include="..\..\Source\UI\GraphEditorPanel.cpp"/>\r
     <ClCompile Include="..\..\Source\UI\MainHostWindow.cpp"/>\r
     <ClCompile Include="..\..\Source\HostStartup.cpp"/>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 71f69c73221b674758c6539628d16cf0ffffd3fb..644f19ed72edaa4d0841a94a74fcb754cf3b1688 100644 (file)
     <ClCompile Include="..\..\Source\HostStartup.cpp">\r
       <Filter>AudioPluginHost\Source</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 563ae87da3eaafa976750d3cd86ce5515b549f58..6e7a859c5778a307a909737ed944b0afd721d4da 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
     <ClCompile Include="..\..\Source\UI\GraphEditorPanel.cpp"/>\r
     <ClCompile Include="..\..\Source\UI\MainHostWindow.cpp"/>\r
     <ClCompile Include="..\..\Source\HostStartup.cpp"/>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 5c056fd722e4a6cf2d4d2dce4f868014855757ce..4cc5b50e3a77a18217aff2a5e914785d93fe3b2a 100644 (file)
     <ClCompile Include="..\..\Source\HostStartup.cpp">\r
       <Filter>AudioPluginHost\Source</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 7022f9a11a551b1196ba15276386fb7e59ae173b..75283ced3375d53127d88a964a6e73a36f8d276e 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_WASAPI=1;JUCE_DIRECTSOUND=1;JUCE_ALSA=1;JUCE_USE_FLAC=0;JUCE_USE_OGGVORBIS=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_AU=1;JUCE_PLUGINHOST_LADSPA=1;JUCE_PLUGINHOST_LV2=1;JUCE_USE_CDREADER=0;JUCE_USE_CDBURNER=0;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\AudioPluginHost.exe</OutputFile>\r
     <ClCompile Include="..\..\Source\UI\GraphEditorPanel.cpp"/>\r
     <ClCompile Include="..\..\Source\UI\MainHostWindow.cpp"/>\r
     <ClCompile Include="..\..\Source\HostStartup.cpp"/>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 46ac064070be2f5a05ea8e34c9705b2968173873..1e37071622a4f5d6132ca20b8e9310529b489fee 100644 (file)
     <ClCompile Include="..\..\Source\HostStartup.cpp">\r
       <Filter>AudioPluginHost\Source</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index a724850956672c4f68fef238e553df729820ff2a..4825c292641cd5b59e631d24ced4535572cf0ec0 100644 (file)
                49453CC5AD9F08D2738464AC /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
                                COMBINE_HIDPI_IMAGES = YES;
                                        "JUCE_CONTENT_SHARING=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                8D1CA827F1EFD443BDCF198A /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_ENABLE_OBJC_WEAK = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+                               IPHONEOS_DEPLOYMENT_TARGET = 11.0;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "Plugin Host";
                                SDKROOT = iphoneos;
                C8B793AC1BEFBE7A99BE8352 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
                                COMBINE_HIDPI_IMAGES = YES;
                                        "JUCE_CONTENT_SHARING=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                C9295196717FABE454A210B7 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_ENABLE_OBJC_WEAK = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+                               IPHONEOS_DEPLOYMENT_TARGET = 11.0;
                                PRODUCT_NAME = "Plugin Host";
                                SDKROOT = iphoneos;
                                TARGETED_DEVICE_FAMILY = "1,2";
index c84518ac8ce5d6d7c3fa31f6bd8e2529aa090ffe..40160cd4c07be02aed2cbb7299767371fbd1f8c6 100644 (file)
@@ -176,11 +176,15 @@ public:
         }\r
 \r
        #if JUCE_IOS || JUCE_ANDROID\r
-        auto screenBounds = Desktop::getInstance().getDisplays().getTotalBounds (true).toFloat();\r
-        auto scaleFactor = jmin ((screenBounds.getWidth() - 50) / getWidth(), (screenBounds.getHeight() - 50) / getHeight());\r
+        const auto screenBounds = Desktop::getInstance().getDisplays().getTotalBounds (true).toFloat();\r
+        const auto scaleFactor = jmin ((screenBounds.getWidth()  - 50.0f) / (float) getWidth(),\r
+                                       (screenBounds.getHeight() - 50.0f) / (float) getHeight());\r
 \r
         if (scaleFactor < 1.0f)\r
-            setSize ((int) (getWidth() * scaleFactor), (int) (getHeight() * scaleFactor));\r
+        {\r
+            setSize ((int) (scaleFactor * (float) getWidth()),\r
+                     (int) (scaleFactor * (float) getHeight()));\r
+        }\r
 \r
         setTopLeftPosition (20, 20);\r
        #else\r
@@ -280,32 +284,17 @@ private:
     //==============================================================================\r
     struct ProgramAudioProcessorEditor  : public AudioProcessorEditor\r
     {\r
-        ProgramAudioProcessorEditor (AudioProcessor& p)  : AudioProcessorEditor (p)\r
+        explicit ProgramAudioProcessorEditor (AudioProcessor& p)\r
+            : AudioProcessorEditor (p)\r
         {\r
             setOpaque (true);\r
 \r
-            addAndMakeVisible (panel);\r
+            addAndMakeVisible (listBox);\r
+            listBox.updateContent();\r
 \r
-            Array<PropertyComponent*> programs;\r
+            const auto rowHeight = listBox.getRowHeight();\r
 \r
-            auto numPrograms = p.getNumPrograms();\r
-            int totalHeight = 0;\r
-\r
-            for (int i = 0; i < numPrograms; ++i)\r
-            {\r
-                auto name = p.getProgramName (i).trim();\r
-\r
-                if (name.isEmpty())\r
-                    name = "Unnamed";\r
-\r
-                auto pc = new PropertyComp (name, p);\r
-                programs.add (pc);\r
-                totalHeight += pc->getPreferredHeight();\r
-            }\r
-\r
-            panel.addProperties (programs);\r
-\r
-            setSize (400, jlimit (25, 400, totalHeight));\r
+            setSize (400, jlimit (rowHeight, 400, p.getNumPrograms() * rowHeight));\r
         }\r
 \r
         void paint (Graphics& g) override\r
@@ -315,33 +304,58 @@ private:
 \r
         void resized() override\r
         {\r
-            panel.setBounds (getLocalBounds());\r
+            listBox.setBounds (getLocalBounds());\r
         }\r
 \r
     private:\r
-        struct PropertyComp  : public PropertyComponent,\r
-                               private AudioProcessorListener\r
+        class Model : public ListBoxModel\r
         {\r
-            PropertyComp (const String& name, AudioProcessor& p)  : PropertyComponent (name), owner (p)\r
+        public:\r
+            Model (Component& o, AudioProcessor& p)\r
+                : owner (o), proc (p) {}\r
+\r
+            int getNumRows() override\r
             {\r
-                owner.addListener (this);\r
+                return proc.getNumPrograms();\r
             }\r
 \r
-            ~PropertyComp() override\r
+            void paintListBoxItem (int rowNumber,\r
+                                   Graphics& g,\r
+                                   int width,\r
+                                   int height,\r
+                                   bool rowIsSelected) override\r
             {\r
-                owner.removeListener (this);\r
+                const auto textColour = owner.findColour (ListBox::textColourId);\r
+\r
+                if (rowIsSelected)\r
+                {\r
+                    const auto defaultColour = owner.findColour (ListBox::backgroundColourId);\r
+                    const auto c = rowIsSelected ? defaultColour.interpolatedWith (textColour, 0.5f)\r
+                                                 : defaultColour;\r
+\r
+                    g.fillAll (c);\r
+                }\r
+\r
+                g.setColour (textColour);\r
+                g.drawText (proc.getProgramName (rowNumber),\r
+                            Rectangle<int> { width, height }.reduced (2),\r
+                            Justification::left,\r
+                            true);\r
             }\r
 \r
-            void refresh() override {}\r
-            void audioProcessorChanged (AudioProcessor*, const ChangeDetails&) override {}\r
-            void audioProcessorParameterChanged (AudioProcessor*, int, float) override {}\r
-\r
-            AudioProcessor& owner;\r
+            void selectedRowsChanged (int row) override\r
+            {\r
+                if (0 <= row)\r
+                    proc.setCurrentProgram (row);\r
+            }\r
 \r
-            JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (PropertyComp)\r
+        private:\r
+            Component& owner;\r
+            AudioProcessor& proc;\r
         };\r
 \r
-        PropertyPanel panel;\r
+        Model model { *this, *getAudioProcessor() };\r
+        ListBox listBox { "Programs", &model };\r
 \r
         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ProgramAudioProcessorEditor)\r
     };\r
index 58dd5d452d0937f1acf861107da931cae105dd98..cdb676f3b1e29e1a87ce9eb64c84c6ce9f88e78c 100644 (file)
@@ -39,12 +39,12 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_CONSOLEAPP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_CONSOLEAPP := BinaryBuilder
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs libcurl) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
@@ -60,12 +60,12 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags libcurl) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_CONSOLEAPP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_CONSOLEAPP := BinaryBuilder
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -Os $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs libcurl) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
index 835c8731c7738b93e2c109554e55868b95c8dcb0..032956a7a8907a7454f062f55947fcbb52c6e97a 100644 (file)
                00F18709927DE6070FBA7BD0 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                COPY_PHASE_STRIP = NO;
                                        "DEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_core=1",
                                        "JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1",
                                        "JUCE_STANDALONE_APPLICATION=1",
                                        "$(inherited)",
                                );
                                INSTALL_PATH = "/usr/bin";
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                PRODUCT_BUNDLE_IDENTIFIER = com.juce.binarybuilder;
                                PRODUCT_NAME = "BinaryBuilder";
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                8A190EF24B99F557190320DA /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                DEAD_CODE_STRIPPING = YES;
                                        "NDEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_core=1",
                                        "JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1",
                                        "JUCE_STANDALONE_APPLICATION=1",
                                );
                                INSTALL_PATH = "/usr/bin";
                                LLVM_LTO = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.11;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                PRODUCT_BUNDLE_IDENTIFIER = com.juce.binarybuilder;
                                PRODUCT_NAME = "BinaryBuilder";
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
index 71be7f930c0ea2cd5a576dc2e11888ae84071687..c8eed5032329504262af26f7309c7622b02f651a 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <WarningLevel>Level4</WarningLevel>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\BinaryBuilder.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <WarningLevel>Level4</WarningLevel>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\BinaryBuilder.exe</OutputFile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
index 5284ca0c1b3ba13488d32bd69b53875aacf58c52..b821c96bfee044ca21d06c97892e97348b1744b6 100644 (file)
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
index 46bfd6a4a7d072ce61f0f70619b656cd4d490ab6..2935ac11fa0bce639ca180ffeec653aa43e7daa8 100644 (file)
@@ -63,7 +63,7 @@ function(_juce_create_atomic_target target_name)
 
     try_compile(compile_result "${test_bindir}" "${test_file_name}"
         OUTPUT_VARIABLE test_build_output_0
-        CXX_STANDARD 14
+        CXX_STANDARD 17
         CXX_STANDARD_REQUIRED TRUE
         CXX_EXTENSIONS FALSE)
 
@@ -71,7 +71,7 @@ function(_juce_create_atomic_target target_name)
         try_compile(compile_result "${test_bindir}" "${test_file_name}"
             OUTPUT_VARIABLE test_build_output_1
             LINK_LIBRARIES atomic
-            CXX_STANDARD 14
+            CXX_STANDARD 17
             CXX_STANDARD_REQUIRED TRUE
             CXX_EXTENSIONS FALSE)
 
@@ -81,7 +81,7 @@ function(_juce_create_atomic_target target_name)
             try_compile(compile_result "${test_bindir}" "${test_file_name}"
                     OUTPUT_VARIABLE test_build_output_2
                     LINK_LIBRARIES atomic
-                    CXX_STANDARD 14
+                    CXX_STANDARD 17
                     CXX_STANDARD_REQUIRED TRUE
                     CXX_EXTENSIONS FALSE)
 
index 555a72c476a34b95fda9a173a08de79f5ae0c17c..25d53400d52d5675ee0c589c0ce25e97af94c49a 100644 (file)
@@ -317,7 +317,7 @@ function(_juce_add_plugin_wrapper_target format path out_path)
     _juce_add_plugin_definitions("${target_name}" INTERFACE ${format})
     _juce_add_standard_defs("${target_name}")
 
-    target_compile_features("${target_name}" INTERFACE cxx_std_14)
+    target_compile_features("${target_name}" INTERFACE cxx_std_17)
     add_library("juce::${target_name}" ALIAS "${target_name}")
 
     if(format STREQUAL "AUv3")
@@ -327,6 +327,7 @@ function(_juce_add_plugin_wrapper_target format path out_path)
             _juce_link_frameworks("${target_name}" INTERFACE AudioUnit)
         endif()
     elseif(format STREQUAL "AU")
+        target_include_directories("${target_name}" INTERFACE "${out_path}/juce_audio_plugin_client/AU")
         _juce_link_frameworks("${target_name}" INTERFACE AudioUnit CoreAudioKit)
     endif()
 endfunction()
@@ -440,6 +441,8 @@ function(juce_add_module module_path)
     _juce_module_sources("${module_path}" "${base_path}" globbed_sources headers)
 
     if(${module_name} STREQUAL "juce_audio_plugin_client")
+        list(REMOVE_ITEM headers "${module_path}/LV2/juce_LV2TurtleDumpProgram.cpp")
+
         _juce_get_platform_plugin_kinds(plugin_kinds)
 
         foreach(kind IN LISTS plugin_kinds)
index 7f7c13b8db90b9881560cda3e2225ea6872b73b0..90f59fbf907776edd9d49e849150d10861a1497e 100644 (file)
@@ -87,12 +87,6 @@ set_property(GLOBAL PROPERTY JUCE_COPY_PLUGIN_AFTER_BUILD FALSE)
 if((CMAKE_SYSTEM_NAME STREQUAL "Linux") OR (CMAKE_SYSTEM_NAME MATCHES ".*BSD"))
     _juce_create_pkgconfig_target(JUCE_CURL_LINUX_DEPS libcurl)
     _juce_create_pkgconfig_target(JUCE_BROWSER_LINUX_DEPS webkit2gtk-4.0 gtk+-x11-3.0)
-elseif(CMAKE_SYSTEM_NAME STREQUAL "Darwin")
-    find_program(JUCE_XCRUN xcrun)
-
-    if(NOT JUCE_XCRUN)
-        message(WARNING "failed to find xcrun; older resource-based AU plug-ins may not work correctly")
-    endif()
 endif()
 
 # We set up default/fallback copy dirs here. If you need different copy dirs, use
@@ -153,67 +147,6 @@ endfunction()
 
 # ==================================================================================================
 
-function(_juce_add_au_resource_fork shared_code_target au_target)
-    if(NOT JUCE_XCRUN)
-        return()
-    endif()
-
-    get_target_property(product_name ${shared_code_target} JUCE_PRODUCT_NAME)
-    get_target_property(module_sources juce::juce_audio_plugin_client_AU INTERFACE_SOURCES)
-
-    list(FILTER module_sources INCLUDE REGEX "/juce_audio_plugin_client_AU.r$")
-
-    if(NOT module_sources)
-        message(FATAL_ERROR "Failed to find AU resource file input")
-    endif()
-
-    list(GET module_sources 0 au_rez_sources)
-
-    get_target_property(juce_library_code ${shared_code_target} JUCE_GENERATED_SOURCES_DIRECTORY)
-    # We don't want our AU AppConfig.h to end up on peoples' include paths if we can help it
-    set(secret_au_resource_dir "${juce_library_code}/${au_target}/secret")
-    set(secret_au_plugindefines "${secret_au_resource_dir}/JucePluginDefines.h")
-
-    set(au_rez_output "${secret_au_resource_dir}/${product_name}.rsrc")
-
-    target_sources(${au_target} PRIVATE "${au_rez_output}")
-    set_source_files_properties("${au_rez_output}" PROPERTIES
-        GENERATED TRUE
-        MACOSX_PACKAGE_LOCATION Resources)
-
-    set(defs_file $<GENEX_EVAL:$<TARGET_PROPERTY:${shared_code_target},JUCE_DEFS_FILE>>)
-
-    # Passing all our compile definitions using generator expressions is really painful
-    # because some of the definitions have pipes and quotes and dollars and goodness-knows
-    # what else that the shell would very much like to claim for itself, thank you very much.
-    # CMake definitely knows how to escape all these things, because it's perfectly happy to pass
-    # them to compiler invocations, but I have no idea how to get it to escape them
-    # in a custom command.
-    # In the end, it's simplest to generate a special single-purpose appconfig just for the
-    # resource compiler.
-    add_custom_command(OUTPUT "${secret_au_plugindefines}"
-        COMMAND juce::juceaide auplugindefines "${defs_file}" "${secret_au_plugindefines}"
-        DEPENDS "${defs_file}"
-        VERBATIM)
-
-    add_custom_command(OUTPUT "${au_rez_output}"
-        COMMAND "${JUCE_XCRUN}" Rez
-            -d "ppc_$ppc" -d "i386_$i386" -d "ppc64_$ppc64" -d "x86_64_$x86_64" -d "arm64_$arm64"
-            -I "${secret_au_resource_dir}"
-            -I "/System/Library/Frameworks/CoreServices.framework/Frameworks/CarbonCore.framework/Versions/A/Headers"
-            -I "${CMAKE_OSX_SYSROOT}/System/Library/Frameworks/AudioUnit.framework/Headers"
-            -isysroot "${CMAKE_OSX_SYSROOT}"
-            "${au_rez_sources}"
-            -useDF
-            -o "${au_rez_output}"
-        DEPENDS "${secret_au_plugindefines}"
-        VERBATIM)
-
-    set(au_resource_directory "$<TARGET_BUNDLE_DIR:${au_target}>/Contents/Resources")
-endfunction()
-
-# ==================================================================================================
-
 # Ideally, we'd check the preprocessor defs on the target to see whether
 # JUCE_USE_CURL, JUCE_WEB_BROWSER, or JUCE_IN_APP_PURCHASES have been explicitly turned off,
 # and then link libraries as appropriate.
@@ -423,7 +356,7 @@ function(juce_add_binary_data target)
 
     target_sources(${target} PRIVATE "${binary_file_names}")
     target_include_directories(${target} INTERFACE ${juce_binary_data_folder})
-    target_compile_features(${target} PRIVATE cxx_std_14)
+    target_compile_features(${target} PRIVATE cxx_std_17)
 
     # This fixes an issue where Xcode is unable to find binary data during archive.
     if(CMAKE_GENERATOR STREQUAL "Xcode")
@@ -871,6 +804,12 @@ function(juce_enable_copy_plugin_step shared_code_target)
     get_target_property(active_targets "${shared_code_target}" JUCE_ACTIVE_PLUGIN_TARGETS)
 
     foreach(target IN LISTS active_targets)
+        get_target_property(target_kind "${target}" JUCE_TARGET_KIND_STRING)
+
+        if(target_kind STREQUAL "App")
+            continue()
+        endif()
+
         get_target_property(source "${target}" JUCE_PLUGIN_ARTEFACT_FILE)
 
         if(source)
@@ -895,6 +834,25 @@ endfunction()
 
 # ==================================================================================================
 
+function(_juce_add_lv2_manifest_helper_target)
+    if(TARGET juce_lv2_helper OR (CMAKE_SYSTEM_NAME STREQUAL "iOS") OR (CMAKE_SYSTEM_NAME STREQUAL "Android"))
+        return()
+    endif()
+
+    get_target_property(module_path juce::juce_audio_plugin_client INTERFACE_JUCE_MODULE_PATH)
+    set(source "${module_path}/juce_audio_plugin_client/LV2/juce_LV2TurtleDumpProgram.cpp")
+    add_executable(juce_lv2_helper "${source}")
+    add_executable(juce::juce_lv2_helper ALIAS juce_lv2_helper)
+    target_compile_features(juce_lv2_helper PRIVATE cxx_std_17)
+    set_target_properties(juce_lv2_helper PROPERTIES BUILD_WITH_INSTALL_RPATH ON)
+    target_link_libraries(juce_lv2_helper PRIVATE ${CMAKE_DL_LIBS})
+    set(THREADS_PREFER_PTHREAD_FLAG ON)
+    find_package(Threads REQUIRED)
+    target_link_libraries(juce_lv2_helper PRIVATE Threads::Threads)
+endfunction()
+
+# ==================================================================================================
+
 function(_juce_set_plugin_target_properties shared_code_target kind)
     set(target_name ${shared_code_target}_${kind})
 
@@ -906,7 +864,15 @@ function(_juce_set_plugin_target_properties shared_code_target kind)
     get_target_property(products_folder ${target_name} LIBRARY_OUTPUT_DIRECTORY)
     set(product_name $<TARGET_PROPERTY:${shared_code_target},JUCE_PRODUCT_NAME>)
 
-    if(kind STREQUAL "VST3")
+    if(kind STREQUAL "Standalone")
+        get_target_property(is_bundle "${target_name}" BUNDLE)
+
+        if(is_bundle)
+            set_target_properties("${target_name}" PROPERTIES JUCE_PLUGIN_ARTEFACT_FILE "$<TARGET_BUNDLE_DIR:${target_name}>")
+        else()
+            set_target_properties("${target_name}" PROPERTIES JUCE_PLUGIN_ARTEFACT_FILE "$<TARGET_FILE:${target_name}>")
+        endif()
+    elseif(kind STREQUAL "VST3")
         set_target_properties(${target_name} PROPERTIES
             BUNDLE_EXTENSION vst3
             PREFIX ""
@@ -1024,8 +990,10 @@ function(_juce_set_plugin_target_properties shared_code_target kind)
         set(output_path "${products_folder}/${product_name}.lv2")
         set_target_properties(${target_name} PROPERTIES LIBRARY_OUTPUT_DIRECTORY "${output_path}")
 
+        _juce_add_lv2_manifest_helper_target()
+
         add_custom_command(TARGET ${target_name} POST_BUILD
-            COMMAND juce::juce_lv2_helper "$<TARGET_FILE:${target_name}>"
+            COMMAND juce_lv2_helper "$<TARGET_FILE:${target_name}>"
             VERBATIM)
 
         _juce_set_copy_properties(${shared_code_target} ${target_name} "${output_path}" JUCE_LV2_COPY_DIR)
@@ -1271,10 +1239,6 @@ function(_juce_configure_plugin_targets target)
         _juce_configure_app_bundle(${target} ${target}_Standalone)
     endif()
 
-    if(TARGET ${target}_AU)
-        _juce_add_au_resource_fork(${target} ${target}_AU)
-    endif()
-
     if(TARGET ${target}_AAX)
         target_link_libraries(${target}_AAX PRIVATE juce_aax_sdk)
     endif()
index 6a77694793138c3efa5da1218be6444916b5f7ba..ef702c13bf3b7a357b397bb1bba5ac5e2dd97a14 100644 (file)
@@ -34,7 +34,7 @@
 \r
   ID:                 juce_build_tools\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE Build Tools\r
   description:        Classes for generating intermediate files for JUCE projects.\r
   website:            http://www.juce.com/juce\r
index 34f1a7f5ffeaae7931381248414788a48f6abe7b..422d8d093eb894cded5a7c6b37dfd345a3d5c38a 100644 (file)
@@ -51,12 +51,52 @@ if(JUCE_BUILD_HELPER_TOOLS)
 else()
     # If we're building using the NDK, the gradle wrapper will try to inject its own compiler using
     # environment variables, which is unfortunate because we really don't want to cross-compile
-    # juceaide. If you really want to set the compilers for juceaide, pass the appropriate
-    # CMAKE_<lang>_COMPILER flags when configuring CMake.
+    # juceaide.
+    # Similarly, when cross-compiling from Linux->Windows (e.g. using
+    # Fedora's mingw64-cmake command), the environment might be configured
+    # for cross-compiling, and we'll need to attempt to put it back to the
+    # host settings in order to build an executable that can run on the host
+    # machine.
     if(CMAKE_CROSSCOMPILING)
+        unset(ENV{ADDR2LINE})
+        unset(ENV{AR})
         unset(ENV{ASM})
+        unset(ENV{AS})
         unset(ENV{CC})
+        unset(ENV{CPP})
+        unset(ENV{CXXFILT})
         unset(ENV{CXX})
+        unset(ENV{DLLTOOL})
+        unset(ENV{DLLWRAP})
+        unset(ENV{ELFEDIT})
+        unset(ENV{GCC})
+        unset(ENV{GCOV_DUMP})
+        unset(ENV{GCOV_TOOL})
+        unset(ENV{GCOV})
+        unset(ENV{GPROF})
+        unset(ENV{GXX})
+        unset(ENV{LDFLAGS})
+        unset(ENV{LD_BFD})
+        unset(ENV{LD})
+        unset(ENV{LTO_DUMP})
+        unset(ENV{NM})
+        unset(ENV{OBJCOPY})
+        unset(ENV{OBJDUMP})
+        unset(ENV{PKG_CONFIG_LIBDIR})
+        unset(ENV{PKG_CONFIG})
+        unset(ENV{RANLIB})
+        unset(ENV{RC})
+        unset(ENV{READELF})
+        unset(ENV{SIZE})
+        unset(ENV{STRINGS})
+        unset(ENV{STRIP})
+        unset(ENV{WIDL})
+        unset(ENV{WINDMC})
+        unset(ENV{WINDRES})
+
+        if(DEFINED ENV{PATH_ORIG})
+            set(ENV{PATH} "$ENV{PATH_ORIG}")
+        endif()
     else()
         # When building with clang-cl in Clion on Windows for an x64 target, the ABI detection phase
         # of the inner build can fail unless we pass through these flags too
index 0892dcad0235f318350f3c1e250217c06b732fda..d36380a908df772249c66313d2166b8d703725dd 100644 (file)
@@ -530,7 +530,7 @@ int main (int argc, char** argv)
         juce::ArgumentList argumentList { arguments.front(),\r
                                           juce::StringArray (arguments.data() + 1, (int) arguments.size() - 1) };\r
 \r
-        using Fn = std::add_lvalue_reference<decltype (writeBinaryData)>::type;\r
+        using Fn = int (*) (juce::ArgumentList&&);\r
 \r
         const std::unordered_map<juce::String, Fn> commands\r
         {\r
index e75d8c21620deabc53af2c07f20c18ff98d1a650..1635dd7f4e652ece63289f6c4d80396ad4e47fae 100644 (file)
@@ -1,8 +1,10 @@
-# Automatically generated makefile, created by the Projucer
+# Automatically generated CMakeLists, created by the Projucer
 # Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!
 
 cmake_minimum_required(VERSION 3.4.1)
 
+project(juce_jni_project)
+
 set(BINARY_NAME "juce_jni")
 
 set(OBOE_DIR "../../../../../modules/juce_audio_devices/native/oboe")
@@ -23,9 +25,9 @@ include_directories( AFTER
 enable_language(ASM)
 
 if(JUCE_BUILD_CONFIGURATION MATCHES "DEBUG")
-    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEBUG=0]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
+    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70005]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCE_DEBUG=0]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DDEBUG=1]] [[-D_DEBUG=1]])
 elseif(JUCE_BUILD_CONFIGURATION MATCHES "RELEASE")
-    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70002]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
+    add_definitions([[-DJUCE_DISPLAY_SPLASH_SCREEN=0]] [[-DJUCE_USE_DARK_SPLASH_SCREEN=1]] [[-DJUCE_PROJUCER_VERSION=0x70005]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1]] [[-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1]] [[-DJUCE_MODULE_AVAILABLE_juce_core=1]] [[-DJUCE_MODULE_AVAILABLE_juce_cryptography=1]] [[-DJUCE_MODULE_AVAILABLE_juce_data_structures=1]] [[-DJUCE_MODULE_AVAILABLE_juce_events=1]] [[-DJUCE_MODULE_AVAILABLE_juce_graphics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1]] [[-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1]] [[-DJUCE_MODULE_AVAILABLE_juce_opengl=1]] [[-DJUCE_MODULE_AVAILABLE_juce_osc=1]] [[-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1]] [[-DJUCE_STANDALONE_APPLICATION=1]] [[-DJUCER_ANDROIDSTUDIO_7F0E4A25=1]] [[-DJUCE_APP_VERSION=1.0.0]] [[-DJUCE_APP_VERSION_HEX=0x10000]] [[-DNDEBUG=1]])
 else()
     message( FATAL_ERROR "No matching build-configuration found." )
 endif()
@@ -40,6 +42,7 @@ add_library( ${BINARY_NAME}
     "../../../Source/ClientComponent.h"
     "../../../Source/SharedCanvas.h"
     "../../../Source/juce_icon.png"
+    "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp"
     "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.h"
@@ -58,6 +61,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPConverters.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPDispatcher.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPFactory.h"
+    "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"
@@ -114,6 +118,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_basics/sources/juce_MemoryAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.h"
+    "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h"
@@ -348,7 +353,6 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
-    "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
@@ -758,6 +762,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h"
     "../../../../../modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h"
+    "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.mm"
@@ -926,6 +931,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_core/native/juce_mac_Strings.mm"
     "../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
     "../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+    "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
     "../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
     "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
     "../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
@@ -1083,6 +1089,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_data_structures/app_properties/juce_ApplicationProperties.h"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.h"
+    "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.h"
@@ -1538,6 +1545,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAWindowProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_WindowsUIAWrapper.h"
+    "../../../../../modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h"
@@ -1557,6 +1565,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+    "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
     "../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
     "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
     "../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
@@ -1641,6 +1650,8 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.h"
@@ -1685,6 +1696,7 @@ add_library( ${BINARY_NAME}
     "../../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"
+    "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.h"
     "../../../../../modules/juce_gui_extra/native/juce_android_PushNotifications.cpp"
     "../../../../../modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"
@@ -1790,6 +1802,7 @@ set_source_files_properties(
     "../../../Source/ClientComponent.h"
     "../../../Source/SharedCanvas.h"
     "../../../Source/juce_icon.png"
+    "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp"
     "../../../../../modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.h"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.cpp"
     "../../../../../modules/juce_audio_basics/buffers/juce_AudioChannelSet.h"
@@ -1808,6 +1821,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPConverters.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPDispatcher.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPFactory.h"
+    "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPIterator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToBytestreamTranslator.h"
     "../../../../../modules/juce_audio_basics/midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"
@@ -1864,6 +1878,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_basics/sources/juce_MemoryAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_MixerAudioSource.h"
+    "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_PositionableAudioSource.h"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.cpp"
     "../../../../../modules/juce_audio_basics/sources/juce_ResamplingAudioSource.h"
@@ -2098,7 +2113,6 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_formats/codecs/flac/ordinals.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_decoder.h"
     "../../../../../modules/juce_audio_formats/codecs/flac/stream_encoder.h"
-    "../../../../../modules/juce_audio_formats/codecs/flac/win_utf8_io.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_51.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/coupled/res_books_stereo.h"
     "../../../../../modules/juce_audio_formats/codecs/oggvorbis/libvorbis-1.3.7/lib/books/floor/floor_books.h"
@@ -2508,6 +2522,7 @@ set_source_files_properties(
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_RangedAudioParameter.h"
     "../../../../../modules/juce_audio_processors/utilities/juce_VST3ClientExtensions.h"
+    "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp"
     "../../../../../modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.h"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.cpp"
     "../../../../../modules/juce_audio_processors/juce_audio_processors.mm"
@@ -2676,6 +2691,7 @@ set_source_files_properties(
     "../../../../../modules/juce_core/native/juce_mac_Strings.mm"
     "../../../../../modules/juce_core/native/juce_mac_SystemStats.mm"
     "../../../../../modules/juce_core/native/juce_mac_Threads.mm"
+    "../../../../../modules/juce_core/native/juce_native_ThreadPriorities.h"
     "../../../../../modules/juce_core/native/juce_posix_IPAddress.h"
     "../../../../../modules/juce_core/native/juce_posix_NamedPipe.cpp"
     "../../../../../modules/juce_core/native/juce_posix_SharedCode.h"
@@ -2833,6 +2849,7 @@ set_source_files_properties(
     "../../../../../modules/juce_data_structures/app_properties/juce_ApplicationProperties.h"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.cpp"
     "../../../../../modules/juce_data_structures/app_properties/juce_PropertiesFile.h"
+    "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoableAction.h"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.cpp"
     "../../../../../modules/juce_data_structures/undomanager/juce_UndoManager.h"
@@ -3288,6 +3305,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAValueProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_UIAWindowProvider.h"
     "../../../../../modules/juce_gui_basics/native/accessibility/juce_win32_WindowsUIAWrapper.h"
+    "../../../../../modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_DragAndDrop.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.cpp"
     "../../../../../modules/juce_gui_basics/native/x11/juce_linux_X11_Symbols.h"
@@ -3307,6 +3325,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/native/juce_mac_MainMenu.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_MouseCursor.mm"
     "../../../../../modules/juce_gui_basics/native/juce_mac_NSViewComponentPeer.mm"
+    "../../../../../modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h"
     "../../../../../modules/juce_gui_basics/native/juce_mac_Windowing.mm"
     "../../../../../modules/juce_gui_basics/native/juce_MultiTouchMapper.h"
     "../../../../../modules/juce_gui_basics/native/juce_ScopedDPIAwarenessDisabler.h"
@@ -3391,6 +3410,8 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_basics/windows/juce_TooltipWindow.h"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.cpp"
     "../../../../../modules/juce_gui_basics/windows/juce_TopLevelWindow.h"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp"
+    "../../../../../modules/juce_gui_basics/windows/juce_VBlankAttachement.h"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.cpp"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.mm"
     "../../../../../modules/juce_gui_basics/juce_gui_basics.h"
@@ -3435,6 +3456,7 @@ set_source_files_properties(
     "../../../../../modules/juce_gui_extra/misc/juce_SplashScreen.h"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_SystemTrayIconComponent.h"
+    "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp"
     "../../../../../modules/juce_gui_extra/misc/juce_WebBrowserComponent.h"
     "../../../../../modules/juce_gui_extra/native/juce_android_PushNotifications.cpp"
     "../../../../../modules/juce_gui_extra/native/juce_android_WebBrowserComponent.cpp"
@@ -3517,14 +3539,12 @@ set_source_files_properties(
     "../../../JuceLibraryCode/JuceHeader.h"
     PROPERTIES HEADER_FILE_ONLY TRUE)
 
-target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
-
 if( JUCE_BUILD_CONFIGURATION MATCHES "DEBUG" )
-    target_compile_options( ${BINARY_NAME} PRIVATE)
+    target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
 endif()
 
 if( JUCE_BUILD_CONFIGURATION MATCHES "RELEASE" )
-    target_compile_options( ${BINARY_NAME} PRIVATE)
+    target_compile_options( ${BINARY_NAME} PRIVATE "-fsigned-char" )
 endif()
 
 find_library(log "log")
index fd520d30037aac4ee09254bac178a03120a479f0..58c8635537f8818164f965cba62a186bb515aa8c 100644 (file)
@@ -1,7 +1,8 @@
 apply plugin: 'com.android.application'
 
 android {
-    compileSdkVersion 30
+    compileSdkVersion 33
+    namespace "com.juce.networkgraphicsdemo"
     externalNativeBuild {
         cmake {
             path "CMakeLists.txt"
@@ -20,10 +21,10 @@ android {
     defaultConfig {
         applicationId "com.juce.networkgraphicsdemo"
         minSdkVersion    16
-        targetSdkVersion 30
+        targetSdkVersion 33
         externalNativeBuild {
             cmake {
-                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-16", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=14", "-DCMAKE_CXX_EXTENSIONS=OFF"
+                arguments "-DANDROID_TOOLCHAIN=clang", "-DANDROID_PLATFORM=android-16", "-DANDROID_STL=c++_static", "-DANDROID_CPP_FEATURES=exceptions rtti", "-DANDROID_ARM_MODE=arm", "-DANDROID_ARM_NEON=TRUE", "-DCMAKE_CXX_STANDARD=17", "-DCMAKE_CXX_EXTENSIONS=OFF"
             }
         }
     }
@@ -51,21 +52,25 @@ android {
             }
             externalNativeBuild {
                 cmake {
-                    arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG", "-DCMAKE_CXX_FLAGS_DEBUG=-Ofast", "-DCMAKE_C_FLAGS_DEBUG=-Ofast"
+                    cFlags    "-Ofast"
+                    cppFlags  "-Ofast"
+                    arguments "-DJUCE_BUILD_CONFIGURATION=DEBUG"
                 }
             }
 
             dimension "default"
-       }
+        }
         release_ {
             externalNativeBuild {
                 cmake {
-                    arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE", "-DCMAKE_CXX_FLAGS_RELEASE=-O3", "-DCMAKE_C_FLAGS_RELEASE=-O3"
+                    cFlags    "-O3"
+                    cppFlags  "-O3"
+                    arguments "-DJUCE_BUILD_CONFIGURATION=RELEASE"
                 }
             }
 
             dimension "default"
-       }
+        }
     }
 
     variantFilter { variant ->
index daf044c3ee8a2e06c330b3c92a94d6d41739a531..e8e438e00a52d5cd0cca4f3b96192bb0c65ad226 100644 (file)
@@ -1,20 +1,18 @@
 <?xml version="1.0" encoding="utf-8"?>
 
-<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0"
-          package="com.juce.networkgraphicsdemo">
+<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0">
   <supports-screens android:smallScreens="true" android:normalScreens="true" android:largeScreens="true" android:anyDensity="true"
                     android:xlargeScreens="true"/>
   <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="28"/>
-  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
-  <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
-  <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
-  <uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
-  <uses-permission android:name="android.permission.BLUETOOTH"/>
+  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_VIDEO"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_IMAGES"/>
+  <uses-permission android:name="android.permission.READ_MEDIA_AUDIO"/>
   <uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
   <uses-permission android:name="android.permission.INTERNET"/>
   <uses-feature android:glEsVersion="0x00020000" android:required="true"/>
   <application android:label="@string/app_name" android:name="com.rmsl.juce.JuceApp" android:icon="@drawable/icon" android:hardwareAccelerated="false">
-    <activity android:name="com.rmsl.juce.JuceActivity" android:label="@string/app_name" android:configChanges="keyboardHidden|orientation|screenSize"
+    <activity android:name="com.rmsl.juce.JuceActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize|navigation"
               android:screenOrientation="unspecified" android:launchMode="singleTask" android:hardwareAccelerated="true"
               android:exported="true">
       <intent-filter>
index ee98c096888d52d441152343876cf1066882fe6a..8e2533a6a8e084f3c9a1cd90818d4b330cbde43d 100644 (file)
@@ -4,7 +4,7 @@ buildscript {
        mavenCentral()
    }
    dependencies {
-       classpath 'com.android.tools.build:gradle:7.0.0'
+       classpath 'com.android.tools.build:gradle:7.3.0'
    }
 }
 
index 80082ba57b11f2c7cdc838256a00336bbde9d498..702c227cd3ad7b11fe3589f2c2d97dbf29504ec6 100644 (file)
@@ -1 +1 @@
-distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip
\ No newline at end of file
+distributionUrl=https\://services.gradle.org/distributions/gradle-7.5.1-all.zip
\ No newline at end of file
index 440409737a5c718f3032fa1cf68c48c015951d98..820afe738be4afbd520ed2ce661047c191d88ad3 100644 (file)
@@ -39,12 +39,12 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := JUCE\ Network\ Graphics\ Demo
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
@@ -60,12 +60,12 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := JUCE\ Network\ Graphics\ Demo
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
index 5d700e9f3af46321a3cfd8a7d8dcb10e63b7a557..4f363192ff3df486e8eac87dfccd1feb3b35c274 100644 (file)
                2E06386CE7CCA5FF76819BFF /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                DEAD_CODE_STRIPPING = YES;
                                        "NDEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
                                LLVM_LTO = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.9;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_LDFLAGS = "-weak_framework Metal -weak_framework MetalKit";
                                PRODUCT_BUNDLE_IDENTIFIER = com.juce.NetworkGraphicsDemo;
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                EE7498599191DDC73ECB55B0 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                COPY_PHASE_STRIP = NO;
                                        "DEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                                INFOPLIST_FILE = Info-App.plist;
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
-                               MACOSX_DEPLOYMENT_TARGET = 10.9;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_LDFLAGS = "-weak_framework Metal -weak_framework MetalKit";
                                PRODUCT_BUNDLE_IDENTIFIER = com.juce.NetworkGraphicsDemo;
index 4296299fdf822478fefdf3b8befa45f13d4a3e29..d4df0a265b514bc45113db0c45cc57ff5687cc57 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <WarningLevel>Level4</WarningLevel>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\JUCE Network Graphics Demo.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <WarningLevel>Level4</WarningLevel>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\JUCE Network Graphics Demo.exe</OutputFile>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
     <ClCompile Include="..\..\Source\Main.cpp"/>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 44a2998b5e428b5daa227aa3efa271adacad1bae..0dc2f237dc784711d5ce48526bc8c22109bd71f5 100644 (file)
     <ClCompile Include="..\..\Source\Main.cpp">\r
       <Filter>NetworkGraphicsDemo\Source</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 4940ed4abaa4c0f7a1964b370ca2cdbc190212c6..12bc5222075c6fa5182ac73dde320298c32b6409 100644 (file)
                2E06386CE7CCA5FF76819BFF /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
                                COMBINE_HIDPI_IMAGES = YES;
                                        "JUCE_CONTENT_SHARING=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
                3BF0365A560ACD4FD24D40CE /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_ENABLE_OBJC_WEAK = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+                               IPHONEOS_DEPLOYMENT_TARGET = 11.0;
                                ONLY_ACTIVE_ARCH = YES;
                                PRODUCT_NAME = "JUCE Network Graphics Demo";
                                SDKROOT = iphoneos;
                9C6D2FD441D79104734762A5 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ALWAYS_SEARCH_USER_PATHS = NO;
                                CLANG_ENABLE_OBJC_WEAK = YES;
                                CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
                                GCC_WARN_UNINITIALIZED_AUTOS = YES;
                                GCC_WARN_UNUSED_FUNCTION = YES;
                                GCC_WARN_UNUSED_VARIABLE = YES;
-                               IPHONEOS_DEPLOYMENT_TARGET = 9.3;
+                               IPHONEOS_DEPLOYMENT_TARGET = 11.0;
                                PRODUCT_NAME = "JUCE Network Graphics Demo";
                                SDKROOT = iphoneos;
                                TARGETED_DEVICE_FAMILY = "1,2";
                EE7498599191DDC73ECB55B0 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
                                ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
                                COMBINE_HIDPI_IMAGES = YES;
                                        "JUCE_CONTENT_SHARING=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_formats=1",
index a6441828dd0f1b48c4fe3005b832ee6e293cb11a..1fd911d40f27e665390cc2ea93deda07f2c4900d 100644 (file)
   <EXPORTFORMATS>\r
     <XCODE_MAC targetFolder="Builds/MacOSX" bigIcon="Ww6bQw" applicationCategory="public.app-category.developer-tools">\r
       <CONFIGURATIONS>\r
-        <CONFIGURATION name="Debug" osxCompatibility="10.9 SDK" isDebug="1" targetName="JUCE Network Graphics Demo"\r
-                       macOSDeploymentTarget="10.9"/>\r
-        <CONFIGURATION name="Release" osxCompatibility="10.9 SDK" isDebug="0" targetName="JUCE Network Graphics Demo"\r
-                       macOSDeploymentTarget="10.9"/>\r
+        <CONFIGURATION name="Debug" isDebug="1" targetName="JUCE Network Graphics Demo"/>\r
+        <CONFIGURATION name="Release" isDebug="0" targetName="JUCE Network Graphics Demo"/>\r
       </CONFIGURATIONS>\r
       <MODULEPATHS>\r
         <MODULEPATH id="juce_core" path="../../modules"/>\r
                    androidCpp11="1" targetFolder="Builds/Android" bigIcon="Ww6bQw"\r
                    gradleToolchainVersion="3.6">\r
       <CONFIGURATIONS>\r
-        <CONFIGURATION name="Debug" isDebug="1" optimisation="6"\r
-                       targetName="JUCE Network Graphics Demo" defines="JUCE_DEBUG=0"/>\r
+        <CONFIGURATION name="Debug" isDebug="1" optimisation="6" targetName="JUCE Network Graphics Demo"\r
+                       defines="JUCE_DEBUG=0"/>\r
         <CONFIGURATION name="Release" isDebug="0" targetName="JUCE Network Graphics Demo"/>\r
       </CONFIGURATIONS>\r
       <MODULEPATHS>\r
index 3f683266195cccb954c81cd3edc2dbdc53238411..4a368ef6d517cba15e0e2c7e67971fd2df8b9907 100644 (file)
@@ -490,7 +490,7 @@ struct MultiLogo  : public BackgroundLogo
 };\r
 \r
 //==============================================================================\r
-void createAllDemos (OwnedArray<AnimatedContent>& demos)\r
+inline void createAllDemos (OwnedArray<AnimatedContent>& demos)\r
 {\r
     demos.add (new FlockDemo());\r
     demos.add (new FlockWithText());\r
index a0f93a7fa3b9c41fd477e32ea603bb2b382e2f4b..139692afa65add803eea669433d7e0123aa2bc30 100644 (file)
@@ -39,12 +39,12 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_build_tools=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_LOG_ASSERTIONS=1" "-DJUCE_USE_CURL=1" "-DJUCE_LOAD_CURL_SYMBOLS_LAZILY=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.2" "-DJUCE_APP_VERSION_HEX=0x70002" $(shell $(PKG_CONFIG) --cflags freetype2) -pthread -I../../JuceLibraryCode -I../../../Build -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_build_tools=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_LOG_ASSERTIONS=1" "-DJUCE_USE_CURL=1" "-DJUCE_LOAD_CURL_SYMBOLS_LAZILY=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.5" "-DJUCE_APP_VERSION_HEX=0x70005" $(shell $(PKG_CONFIG) --cflags freetype2) -pthread -I../../JuceLibraryCode -I../../../Build -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := Projucer
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs freetype2) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
@@ -60,12 +60,12 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_build_tools=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_LOG_ASSERTIONS=1" "-DJUCE_USE_CURL=1" "-DJUCE_LOAD_CURL_SYMBOLS_LAZILY=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.2" "-DJUCE_APP_VERSION_HEX=0x70002" $(shell $(PKG_CONFIG) --cflags freetype2) -pthread -I../../JuceLibraryCode -I../../../Build -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_build_tools=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_LOG_ASSERTIONS=1" "-DJUCE_USE_CURL=1" "-DJUCE_LOAD_CURL_SYMBOLS_LAZILY=1" "-DJUCE_ALLOW_STATIC_NULL_VARIABLES=0" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_WEB_BROWSER=0" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=7.0.5" "-DJUCE_APP_VERSION_HEX=0x70005" $(shell $(PKG_CONFIG) --cflags freetype2) -pthread -I../../JuceLibraryCode -I../../../Build -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_APP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_APP := Projucer
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs freetype2) -fvisibility=hidden -lrt -ldl -lpthread $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
index 255ae69c3ac3a7f5ab873dd24c085bcb59e0f1b0..82442e0f434f3cf156721200a530f5fa6cf5bc81 100644 (file)
@@ -22,9 +22,9 @@
     <key>CFBundleSignature</key>\r
     <string>????</string>\r
     <key>CFBundleShortVersionString</key>\r
-    <string>7.0.2</string>\r
+    <string>7.0.5</string>\r
     <key>CFBundleVersion</key>\r
-    <string>7.0.2</string>\r
+    <string>7.0.5</string>\r
     <key>NSHumanReadableCopyright</key>\r
     <string>Raw Material Software Limited</string>\r
     <key>NSHighResolutionCapable</key>\r
index ff3b8511d66f8278d8d6ba69a0d484dddca5f42c..68b0ed3a9c71a4c03e02267c6f7cc01121c0261a 100644 (file)
                0BC15DC2E5FE5ECFFB398D49 /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                DEAD_CODE_STRIPPING = YES;
                                        "NDEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_build_tools=1",
                                        "JUCE_MODULE_AVAILABLE_juce_core=1",
                                        "JUCE_MODULE_AVAILABLE_juce_cryptography=1",
                                        "JUCE_WEB_BROWSER=0",
                                        "JUCE_STANDALONE_APPLICATION=1",
                                        "JUCER_XCODE_MAC_F6D2F4CF=1",
-                                       "JUCE_APP_VERSION=7.0.2",
-                                       "JUCE_APP_VERSION_HEX=0x70002",
+                                       "JUCE_APP_VERSION=7.0.5",
+                                       "JUCE_APP_VERSION_HEX=0x70005",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                INFOPLIST_FILE = Info-App.plist;
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
-                               MACOSX_DEPLOYMENT_TARGET = 10.12;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../Build $(SRCROOT)/../../../../modules";
                                OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                0CC6C439D038EDA0D7F10DF0 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                COPY_PHASE_STRIP = NO;
                                        "DEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_build_tools=1",
                                        "JUCE_MODULE_AVAILABLE_juce_core=1",
                                        "JUCE_MODULE_AVAILABLE_juce_cryptography=1",
                                        "JUCE_WEB_BROWSER=0",
                                        "JUCE_STANDALONE_APPLICATION=1",
                                        "JUCER_XCODE_MAC_F6D2F4CF=1",
-                                       "JUCE_APP_VERSION=7.0.2",
-                                       "JUCE_APP_VERSION_HEX=0x70002",
+                                       "JUCE_APP_VERSION=7.0.5",
+                                       "JUCE_APP_VERSION_HEX=0x70005",
                                        "JucePlugin_Build_VST=0",
                                        "JucePlugin_Build_VST3=0",
                                        "JucePlugin_Build_AU=0",
                                INFOPLIST_FILE = Info-App.plist;
                                INFOPLIST_PREPROCESS = NO;
                                INSTALL_PATH = "$(HOME)/Applications";
-                               MACOSX_DEPLOYMENT_TARGET = 10.12;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../Build $(SRCROOT)/../../../../modules";
                                OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
index 83c0c597ba2e661de3d705ddab93b64263ddd0d8..eaab8066a712ec8a84acb87b55ab16b5c6fc3549 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 748c79a530bbc3e5b9b06ef043a7b7519ac0bae7..c01b7709240e615673b2dad0df69e2954737fd45 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 842cf6811448db2d1d3e7d284626030b0610eb5c..9fdaf39398920d0c32e92ecd9df6e20e3026ed27 100644 (file)
@@ -9,7 +9,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  7,0,2,0\r
+FILEVERSION  7,0,5,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -18,9 +18,9 @@ BEGIN
       VALUE "CompanyName",  "Raw Material Software Limited\0"\r
       VALUE "LegalCopyright",  "Raw Material Software Limited\0"\r
       VALUE "FileDescription",  "Projucer\0"\r
-      VALUE "FileVersion",  "7.0.2\0"\r
+      VALUE "FileVersion",  "7.0.5\0"\r
       VALUE "ProductName",  "Projucer\0"\r
-      VALUE "ProductVersion",  "7.0.2\0"\r
+      VALUE "ProductVersion",  "7.0.5\0"\r
     END\r
   END\r
 \r
index ba0a4ff2465ace8ea3045ab23622600e1f1f2b8e..5563032f1c9481ce6fe4356c26e19e189aeccf95 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index c3b4cd56b4177c6b3b4bdb0282b94a7ff1731620..bf82efb3dc3b75426692fb98e4044fa822248a3c 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 842cf6811448db2d1d3e7d284626030b0610eb5c..9fdaf39398920d0c32e92ecd9df6e20e3026ed27 100644 (file)
@@ -9,7 +9,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  7,0,2,0\r
+FILEVERSION  7,0,5,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -18,9 +18,9 @@ BEGIN
       VALUE "CompanyName",  "Raw Material Software Limited\0"\r
       VALUE "LegalCopyright",  "Raw Material Software Limited\0"\r
       VALUE "FileDescription",  "Projucer\0"\r
-      VALUE "FileVersion",  "7.0.2\0"\r
+      VALUE "FileVersion",  "7.0.5\0"\r
       VALUE "ProductName",  "Projucer\0"\r
-      VALUE "ProductVersion",  "7.0.2\0"\r
+      VALUE "ProductVersion",  "7.0.5\0"\r
     END\r
   END\r
 \r
index 6a8f866dab7dca02b5eabce6efcef6bf8f8f44d8..a6b64ae1921d21352164c6bbf8c58dad72418567 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreaded</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\Build;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.2;JUCE_APP_VERSION_HEX=0x70002;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_build_tools=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_LOG_ASSERTIONS=1;JUCE_USE_CURL=1;JUCE_LOAD_CURL_SYMBOLS_LAZILY=1;JUCE_ALLOW_STATIC_NULL_VARIABLES=0;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_WEB_BROWSER=0;JUCE_STANDALONE_APPLICATION=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=7.0.5;JUCE_APP_VERSION_HEX=0x70005;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\Projucer.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index dcac9aaeec30910ff88cd8014fde9cb4afcc965c..3e3eb44572be13188419fc91afaefe1dea58553c 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 842cf6811448db2d1d3e7d284626030b0610eb5c..9fdaf39398920d0c32e92ecd9df6e20e3026ed27 100644 (file)
@@ -9,7 +9,7 @@
 #include <windows.h>\r
 \r
 VS_VERSION_INFO VERSIONINFO\r
-FILEVERSION  7,0,2,0\r
+FILEVERSION  7,0,5,0\r
 BEGIN\r
   BLOCK "StringFileInfo"\r
   BEGIN\r
@@ -18,9 +18,9 @@ BEGIN
       VALUE "CompanyName",  "Raw Material Software Limited\0"\r
       VALUE "LegalCopyright",  "Raw Material Software Limited\0"\r
       VALUE "FileDescription",  "Projucer\0"\r
-      VALUE "FileVersion",  "7.0.2\0"\r
+      VALUE "FileVersion",  "7.0.5\0"\r
       VALUE "ProductName",  "Projucer\0"\r
-      VALUE "ProductVersion",  "7.0.2\0"\r
+      VALUE "ProductVersion",  "7.0.5\0"\r
     END\r
   END\r
 \r
index 6e76a0076f3df75c126ce5bfeb23c7e00bff20d4..012eda673f22e579ddc8d407df8b2888fd70c856 100644 (file)
@@ -30,10 +30,6 @@ juce_add_gui_app(Projucer
 
 juce_generate_juce_header(Projucer)
 
-# This is to work around a bug with how cmake computes language standard flags with
-# target_compile_features
-set_target_properties(Projucer PROPERTIES CXX_STANDARD 11)
-
 target_sources(Projucer PRIVATE
     Source/Application/jucer_AutoUpdater.cpp
     Source/Application/jucer_CommandLine.cpp
index 1653f92775cb0b5d73c2dbeb973802741283eecf..a7678ade707e2ce6771f552909913766ccd44362 100644 (file)
@@ -44,7 +44,7 @@ namespace ProjectInfo
 {\r
     const char* const  projectName    = "Projucer";\r
     const char* const  companyName    = "Raw Material Software Limited";\r
-    const char* const  versionString  = "7.0.2";\r
-    const int          versionNumber  = 0x70002;\r
+    const char* const  versionString  = "7.0.5";\r
+    const int          versionNumber  = 0x70005;\r
 }\r
 #endif\r
index d27c80ca87415b68b12d93301d8ae76360658a16..f836208ca6e8582720447f6a1d0c4687bb60b4e2 100644 (file)
@@ -1,7 +1,7 @@
 <?xml version="1.0" encoding="UTF-8"?>\r
 \r
 <JUCERPROJECT id="M70qfTRRk" name="Projucer" projectType="guiapp" juceFolder="../../juce"\r
-              version="7.0.2" bundleIdentifier="com.juce.theprojucer" splashScreenColour="Dark"\r
+              version="7.0.5" bundleIdentifier="com.juce.theprojucer" splashScreenColour="Dark"\r
               displaySplashScreen="0" reportAppUsage="0" companyName="Raw Material Software Limited"\r
               companyCopyright="Raw Material Software Limited" useAppConfig="0"\r
               addUsingNamespaceToJuceHeader="1" jucerFormatVersion="1">\r
@@ -12,9 +12,9 @@
                applicationCategory="public.app-category.developer-tools">\r
       <CONFIGURATIONS>\r
         <CONFIGURATION name="Debug" isDebug="1" targetName="Projucer" cppLibType="libc++"\r
-                       recommendedWarnings="LLVM" macOSDeploymentTarget="10.12"/>\r
+                       recommendedWarnings="LLVM"/>\r
         <CONFIGURATION name="Release" isDebug="0" targetName="Projucer" cppLibType="libc++"\r
-                       linkTimeOptimisation="0" recommendedWarnings="LLVM" macOSDeploymentTarget="10.12"/>\r
+                       linkTimeOptimisation="0" recommendedWarnings="LLVM"/>\r
       </CONFIGURATIONS>\r
       <MODULEPATHS>\r
         <MODULEPATH id="juce_gui_extra" path="../../modules"/>\r
index 3b6fed5ae05be123668d5a6908b719fd75a58e3b..204d649be564a14457fe3b60631d4d3b9e7e15d0 100644 (file)
@@ -44,7 +44,7 @@ void LatestVersionCheckerAndUpdater::checkForNewVersion (bool background)
     if (! isThreadRunning())\r
     {\r
         backgroundCheck = background;\r
-        startThread (3);\r
+        startThread (Priority::low);\r
     }\r
 }\r
 \r
@@ -373,7 +373,7 @@ public:
         : ThreadWithProgressWindow ("Downloading New Version", true, true),\r
           asset (a), targetFolder (t), completionCallback (std::move (cb))\r
     {\r
-        launchThread (3);\r
+        launchThread (Priority::low);\r
     }\r
 \r
 private:\r
index cfecff482902d0f042594f021f9059fd793dadcc..7873dd7482ace9e15cf677b16ebcea5ccdc603e0 100644 (file)
@@ -27,8 +27,7 @@
 \r
 \r
 //==============================================================================\r
-// The GCC extensions define linux somewhere in the headers, so undef it here...\r
-#if JUCE_GCC\r
+#ifdef linux\r
  #undef linux\r
 #endif\r
 \r
index e12f5fada2119556049a79858c6b65d78314e23f..7a7e71600e1d810439ed9943851cab553d7074aa 100644 (file)
@@ -1433,9 +1433,9 @@ PathPoint PathPoint::withChangedPointType (const Path::Iterator::PathElementType
             p.pos [numPoints - 1] = p.pos [oldNumPoints - 1];\r
             p.pos [numPoints - 1].getRectangleDouble (x, y, w, h, parentArea, owner->getDocument()->getComponentLayout());\r
 \r
-            const int index = owner->points.indexOf (this);\r
+            const int index = owner->indexOfPoint (this);\r
 \r
-            if (PathPoint* lastPoint = owner->points [index - 1])\r
+            if (PathPoint* lastPoint = owner->getPoint (index - 1))\r
             {\r
                 lastPoint->pos [lastPoint->getNumPoints() - 1]\r
                             .getRectangleDouble (lastX, lastY, w, h, parentArea, owner->getDocument()->getComponentLayout());\r
@@ -1486,7 +1486,7 @@ void PathPoint::getEditableProperties (Array<PropertyComponent*>& props, bool mu
     if (multipleSelected)\r
         return;\r
 \r
-    auto index = owner->points.indexOf (this);\r
+    auto index = owner->indexOfPoint (this);\r
     jassert (index >= 0);\r
 \r
     switch (type)\r
@@ -1537,7 +1537,7 @@ void PathPoint::getEditableProperties (Array<PropertyComponent*>& props, bool mu
 \r
 void PathPoint::deleteFromPath()\r
 {\r
-    owner->deletePoint (owner->points.indexOf (this), true);\r
+    owner->deletePoint (owner->indexOfPoint (this), true);\r
 }\r
 \r
 //==============================================================================\r
@@ -1554,7 +1554,7 @@ PathPointComponent::PathPointComponent (PaintElementPath* const path_,
     setSize (11, 11);\r
     setRepaintsOnMouseActivity (true);\r
 \r
-    selected = routine->getSelectedPoints().isSelected (path_->points [index]);\r
+    selected = routine->getSelectedPoints().isSelected (path_->getPoint (index));\r
     routine->getSelectedPoints().addChangeListener (this);\r
 }\r
 \r
@@ -1614,7 +1614,7 @@ void PathPointComponent::mouseDown (const MouseEvent& e)
     dragX = getX() + getWidth() / 2;\r
     dragY = getY() + getHeight() / 2;\r
 \r
-    mouseDownSelectStatus = routine->getSelectedPoints().addToSelectionOnMouseDown (path->points [index], e.mods);\r
+    mouseDownSelectStatus = routine->getSelectedPoints().addToSelectionOnMouseDown (path->getPoint (index), e.mods);\r
 \r
     owner->getDocument()->beginTransaction();\r
 }\r
@@ -1646,7 +1646,7 @@ void PathPointComponent::mouseDrag (const MouseEvent& e)
 \r
 void PathPointComponent::mouseUp (const MouseEvent& e)\r
 {\r
-    routine->getSelectedPoints().addToSelectionOnMouseUp (path->points [index],\r
+    routine->getSelectedPoints().addToSelectionOnMouseUp (path->getPoint (index),\r
                                                           e.mods, dragging,\r
                                                           mouseDownSelectStatus);\r
 }\r
@@ -1655,7 +1655,7 @@ void PathPointComponent::changeListenerCallback (ChangeBroadcaster* source)
 {\r
     ElementSiblingComponent::changeListenerCallback (source);\r
 \r
-    const bool nowSelected = routine->getSelectedPoints().isSelected (path->points [index]);\r
+    const bool nowSelected = routine->getSelectedPoints().isSelected (path->getPoint (index));\r
 \r
     if (nowSelected != selected)\r
     {\r
index fc1eb504cabba1a125e8e28332df80ced0a7d8a8..d6a949f835dfd1616c6eaf88b121a7a465c7de07 100644 (file)
@@ -70,21 +70,21 @@ public:
     //==============================================================================\r
     void setInitialBounds (int parentWidth, int parentHeight) override;\r
     Rectangle<int> getCurrentBounds (const Rectangle<int>& parentArea) const override;\r
-    void setCurrentBounds (const Rectangle<int>& b, const Rectangle<int>& parentArea, const bool undoable) override;\r
+    void setCurrentBounds (const Rectangle<int>& b, const Rectangle<int>& parentArea, bool undoable) override;\r
 \r
     //==============================================================================\r
     bool getPoint (int index, int pointNumber, double& x, double& y, const Rectangle<int>& parentArea) const;\r
-    void movePoint (int index, int pointNumber, double newX, double newY, const Rectangle<int>& parentArea, const bool undoable);\r
+    void movePoint (int index, int pointNumber, double newX, double newY, const Rectangle<int>& parentArea, bool undoable);\r
 \r
     RelativePositionedRectangle getPoint (int index, int pointNumber) const;\r
-    void setPoint (int index, int pointNumber, const RelativePositionedRectangle& newPoint, const bool undoable);\r
+    void setPoint (int index, int pointNumber, const RelativePositionedRectangle& newPoint, bool undoable);\r
 \r
     int getNumPoints() const noexcept                                    { return points.size(); }\r
     PathPoint* getPoint (int index) const noexcept                       { return points [index]; }\r
-    int indexOfPoint (PathPoint* const p) const noexcept                 { return points.indexOf (p); }\r
+    int indexOfPoint (const PathPoint* p) const noexcept                 { return points.indexOf (p); }\r
 \r
-    PathPoint* addPoint (int pointIndexToAddItAfter, const bool undoable);\r
-    void deletePoint (int pointIndex, const bool undoable);\r
+    PathPoint* addPoint (int pointIndexToAddItAfter, bool undoable);\r
+    void deletePoint (int pointIndex, bool undoable);\r
 \r
     void pointListChanged();\r
 \r
@@ -92,10 +92,10 @@ public:
 \r
     //==============================================================================\r
     bool isSubpathClosed (int pointIndex) const;\r
-    void setSubpathClosed (int pointIndex, const bool closed, const bool undoable);\r
+    void setSubpathClosed (int pointIndex, bool closed, bool undoable);\r
 \r
     bool isNonZeroWinding() const noexcept                               { return nonZeroWinding; }\r
-    void setNonZeroWinding (const bool nonZero, const bool undoable);\r
+    void setNonZeroWinding (bool nonZero, bool undoable);\r
 \r
     //==============================================================================\r
     void getEditableProperties (Array<PropertyComponent*>& props, bool multipleSelected) override;\r
@@ -125,8 +125,6 @@ public:
     void changed() override;\r
 \r
 private:\r
-    friend class PathPoint;\r
-    friend class PathPointComponent;\r
     OwnedArray<PathPoint> points;\r
     bool nonZeroWinding;\r
     mutable Path path;\r
index cb2eb306d288eb7e969aa4cfc83a514383d2109c..68eb64cc341976f8577f045b45f3faa1a83a2792 100644 (file)
@@ -120,6 +120,8 @@ public:
 \r
     void perform (UndoableAction* action, const String& actionName);\r
 \r
+    void moveComponentZOrder (int oldIndex, int newIndex);\r
+\r
 private:\r
     JucerDocument* document;\r
     OwnedArray<Component> components;\r
@@ -127,10 +129,6 @@ private:
     int nextCompUID;\r
 \r
     String getUnusedMemberName (String nameRoot, Component* comp) const;\r
-\r
-    friend class FrontBackCompAction;\r
-    friend class DeleteCompAction;\r
-    void moveComponentZOrder (int oldIndex, int newIndex);\r
 };\r
 \r
 void positionToCode (const RelativePositionedRectangle& position,\r
index 111c0f098c959e89809ed5d6a2cd2b308270de0e..9c4b1eec3cc7a6d3cde71b39ae08c90f49bda518 100644 (file)
@@ -573,7 +573,7 @@ bool JucerDocument::reloadFromDocument()
     if (currentXML != nullptr && currentXML->isEquivalentTo (newXML.get(), true))\r
         return true;\r
 \r
-    currentXML.reset (newXML.release());\r
+    currentXML = std::move (newXML);\r
     stopTimer();\r
 \r
     resources.loadFromCpp (getCppFile(), cppContent);\r
index b8c6cc4ce68eee79721fe726e0948ee7a3c22b13..67e0d7caa5ff9184320402fcb25190a4f084154a 100644 (file)
@@ -46,23 +46,23 @@ public:
 \r
     //==============================================================================\r
     int getNumElements() const noexcept                                     { return elements.size(); }\r
-    PaintElement* getElement (const int index) const noexcept               { return elements [index]; }\r
+    PaintElement* getElement (int index) const noexcept                     { return elements [index]; }\r
     int indexOfElement (PaintElement* e) const noexcept                     { return elements.indexOf (e); }\r
     bool containsElement (PaintElement* e) const noexcept                   { return elements.contains (e); }\r
 \r
     //==============================================================================\r
     void clear();\r
-    PaintElement* addElementFromXml (const XmlElement& xml, const int index, const bool undoable);\r
-    PaintElement* addNewElement (PaintElement* elementToCopy, const int index, const bool undoable);\r
-    void removeElement (PaintElement* element, const bool undoable);\r
+    PaintElement* addElementFromXml (const XmlElement& xml, int index, bool undoable);\r
+    PaintElement* addNewElement (PaintElement* elementToCopy, int index, bool undoable);\r
+    void removeElement (PaintElement* element, bool undoable);\r
 \r
-    void elementToFront (PaintElement* element, const bool undoable);\r
-    void elementToBack (PaintElement* element, const bool undoable);\r
+    void elementToFront (PaintElement* element, bool undoable);\r
+    void elementToBack (PaintElement* element, bool undoable);\r
 \r
-    const Colour getBackgroundColour() const noexcept                       { return backgroundColour; }\r
+    Colour getBackgroundColour() const noexcept                       { return backgroundColour; }\r
     void setBackgroundColour (Colour newColour) noexcept;\r
 \r
-    void fillWithBackground (Graphics& g, const bool drawOpaqueBackground);\r
+    void fillWithBackground (Graphics& g, bool drawOpaqueBackground);\r
     void drawElements (Graphics& g, const Rectangle<int>& relativeTo);\r
 \r
     void dropImageAt (const File& f, int x, int y);\r
@@ -108,6 +108,8 @@ public:
     void applyCustomPaintSnippets (StringArray&);\r
 \r
     //==============================================================================\r
+    void moveElementZOrder (int oldIndex, int newIndex);\r
+\r
 private:\r
     OwnedArray<PaintElement> elements;\r
     SelectedItemSet <PaintElement*> selectedElements;\r
@@ -115,8 +117,4 @@ private:
     JucerDocument* document;\r
 \r
     Colour backgroundColour;\r
-\r
-    friend class DeleteElementAction;\r
-    friend class FrontOrBackElementAction;\r
-    void moveElementZOrder (int oldIndex, int newIndex);\r
 };\r
index 927ef5e32f4cd4803f0763a953111bdbaa21a43b..fa894d342c9e7c89880d3edc0dd5dfda6a1b8547 100644 (file)
@@ -185,7 +185,7 @@ public:
             findPanel      = (1 << 2)\r
         };\r
 \r
-        JUCE_NODISCARD AdditionalComponents with (Type t)\r
+        [[nodiscard]] AdditionalComponents with (Type t)\r
         {\r
             auto copy = *this;\r
             copy.componentTypes |= t;\r
index d0b8c2ac49be4223ba4bdd28148bb98333b63daf..6f350c4be49a3fc2074ac3c9b216b5a19da0da3a 100644 (file)
@@ -236,7 +236,7 @@ bool Project::setCppVersionFromOldExporterSettings()
         }\r
     }\r
 \r
-    if (highestLanguageStandard >= 14)\r
+    if (highestLanguageStandard >= 17)\r
     {\r
         cppStandardValue = highestLanguageStandard;\r
         return true;\r
@@ -247,8 +247,14 @@ bool Project::setCppVersionFromOldExporterSettings()
 \r
 void Project::updateDeprecatedProjectSettings()\r
 {\r
-    if (cppStandardValue.get().toString() == "11")\r
-        cppStandardValue.resetToDefault();\r
+    for (const auto& version : { "11", "14" })\r
+    {\r
+        if (cppStandardValue.get().toString() == version)\r
+        {\r
+            cppStandardValue.resetToDefault();\r
+            break;\r
+        }\r
+    }\r
 \r
     for (ExporterIterator exporter (*this); exporter.next();)\r
         exporter->updateDeprecatedSettings();\r
@@ -299,7 +305,7 @@ void Project::initialiseProjectValues()
     useAppConfigValue.referTo             (projectRoot, Ids::useAppConfig,                  getUndoManager(), true);\r
     addUsingNamespaceToJuceHeader.referTo (projectRoot, Ids::addUsingNamespaceToJuceHeader, getUndoManager(), true);\r
 \r
-    cppStandardValue.referTo (projectRoot, Ids::cppLanguageStandard, getUndoManager(), "14");\r
+    cppStandardValue.referTo (projectRoot, Ids::cppLanguageStandard, getUndoManager(), "17");\r
 \r
     headerSearchPathsValue.referTo   (projectRoot, Ids::headerPath, getUndoManager());\r
     preprocessorDefsValue.referTo    (projectRoot, Ids::defines,    getUndoManager());\r
@@ -1717,7 +1723,8 @@ Value Project::Item::getShouldSkipPCHValue()                { return state.getPr
 bool Project::Item::shouldSkipPCH() const                   { return isModuleCode() || state [Ids::skipPCH]; }\r
 \r
 Value Project::Item::getCompilerFlagSchemeValue()           { return state.getPropertyAsValue (Ids::compilerFlagScheme, getUndoManager()); }\r
-String Project::Item::getCompilerFlagSchemeString() const   { return state [Ids::compilerFlagScheme]; }\r
+\r
+String Project::Item::getCompilerFlagSchemeString() const   { return state[Ids::compilerFlagScheme]; }\r
 \r
 void Project::Item::setCompilerFlagScheme (const String& scheme)\r
 {\r
index 0340168137463eadb6f5495f953d6e56a2ba5d42..ae976c1e81d4490cfc83458dde1bbdd0befd5037 100644 (file)
@@ -220,8 +220,8 @@ public:
     bool shouldDisplaySplashScreen() const               { return displaySplashScreenValue.get(); }\r
     String getSplashScreenColourString() const           { return splashScreenColourValue.get(); }\r
 \r
-    static StringArray getCppStandardStrings()           { return { "C++14", "C++17", "C++20", "Use Latest" }; }\r
-    static Array<var> getCppStandardVars()               { return { "14",    "17",    "20",    "latest" }; }\r
+    static StringArray getCppStandardStrings()           { return { "C++17", "C++20", "Use Latest" }; }\r
+    static Array<var> getCppStandardVars()               { return { "17",    "20",    "latest" }; }\r
 \r
     static String getLatestNumberedCppStandardString()\r
     {\r
index 9021db21f5e31fb5e2e464469bd41f2f0004da12..a030a95940fd6244d7aefb518ffbcb1064619073 100644 (file)
@@ -71,6 +71,12 @@ public:
         createOtherExporterProperties (props);\r
     }\r
 \r
+    void updateDeprecatedSettings() override\r
+    {\r
+        updateExternalReadPermission();\r
+        updateBluetoothPermission();\r
+    }\r
+\r
     static String getDisplayName()        { return "Android"; }\r
     static String getValueTreeTypeName()  { return "ANDROIDSTUDIO"; }\r
     static String getTargetFolderName()   { return "Android"; }\r
@@ -94,7 +100,9 @@ public:
                                  androidCustomActivityClass, androidCustomApplicationClass, androidManifestCustomXmlElements,\r
                                  androidGradleSettingsContent, androidVersionCode, androidMinimumSDK, androidTargetSDK, androidTheme,\r
                                  androidExtraAssetsFolder, androidOboeRepositoryPath, androidInternetNeeded, androidMicNeeded, androidCameraNeeded,\r
-                                 androidBluetoothNeeded, androidExternalReadPermission, androidExternalWritePermission,\r
+                                 androidBluetoothScanNeeded, androidBluetoothAdvertiseNeeded, androidBluetoothConnectNeeded,\r
+                                 androidReadMediaAudioPermission, androidReadMediaImagesPermission,\r
+                                 androidReadMediaVideoPermission, androidExternalWritePermission,\r
                                  androidInAppBillingPermission, androidVibratePermission, androidOtherPermissions, androidPushNotifications,\r
                                  androidEnableRemoteNotifications, androidRemoteNotificationsConfigFile, androidEnableContentSharing, androidKeyStore,\r
                                  androidKeyStorePass, androidKeyAlias, androidKeyAliasPass, gradleVersion, gradleToolchain, androidPluginVersion;\r
@@ -116,15 +124,19 @@ public:
           androidGradleSettingsContent         (settings, Ids::androidGradleSettingsContent,         getUndoManager()),\r
           androidVersionCode                   (settings, Ids::androidVersionCode,                   getUndoManager(), "1"),\r
           androidMinimumSDK                    (settings, Ids::androidMinimumSDK,                    getUndoManager(), "16"),\r
-          androidTargetSDK                     (settings, Ids::androidTargetSDK,                     getUndoManager(), "30"),\r
+          androidTargetSDK                     (settings, Ids::androidTargetSDK,                     getUndoManager(), "33"),\r
           androidTheme                         (settings, Ids::androidTheme,                         getUndoManager()),\r
           androidExtraAssetsFolder             (settings, Ids::androidExtraAssetsFolder,             getUndoManager()),\r
           androidOboeRepositoryPath            (settings, Ids::androidOboeRepositoryPath,            getUndoManager()),\r
           androidInternetNeeded                (settings, Ids::androidInternetNeeded,                getUndoManager(), true),\r
           androidMicNeeded                     (settings, Ids::microphonePermissionNeeded,           getUndoManager(), false),\r
           androidCameraNeeded                  (settings, Ids::cameraPermissionNeeded,               getUndoManager(), false),\r
-          androidBluetoothNeeded               (settings, Ids::androidBluetoothNeeded,               getUndoManager(), true),\r
-          androidExternalReadPermission        (settings, Ids::androidExternalReadNeeded,            getUndoManager(), true),\r
+          androidBluetoothScanNeeded           (settings, Ids::androidBluetoothScanNeeded,           getUndoManager(), false),\r
+          androidBluetoothAdvertiseNeeded      (settings, Ids::androidBluetoothAdvertiseNeeded,      getUndoManager(), false),\r
+          androidBluetoothConnectNeeded        (settings, Ids::androidBluetoothConnectNeeded,        getUndoManager(), false),\r
+          androidReadMediaAudioPermission      (settings, Ids::androidReadMediaAudioPermission,      getUndoManager(), true),\r
+          androidReadMediaImagesPermission     (settings, Ids::androidReadMediaImagesPermission,     getUndoManager(), true),\r
+          androidReadMediaVideoPermission      (settings, Ids::androidReadMediaVideoPermission,      getUndoManager(), true),\r
           androidExternalWritePermission       (settings, Ids::androidExternalWriteNeeded,           getUndoManager(), true),\r
           androidInAppBillingPermission        (settings, Ids::androidInAppBilling,                  getUndoManager(), false),\r
           androidVibratePermission             (settings, Ids::androidVibratePermissionNeeded,       getUndoManager(), false),\r
@@ -137,9 +149,9 @@ public:
           androidKeyStorePass                  (settings, Ids::androidKeyStorePass,                  getUndoManager(), "android"),\r
           androidKeyAlias                      (settings, Ids::androidKeyAlias,                      getUndoManager(), "androiddebugkey"),\r
           androidKeyAliasPass                  (settings, Ids::androidKeyAliasPass,                  getUndoManager(), "android"),\r
-          gradleVersion                        (settings, Ids::gradleVersion,                        getUndoManager(), "7.0.2"),\r
+          gradleVersion                        (settings, Ids::gradleVersion,                        getUndoManager(), "7.5.1"),\r
           gradleToolchain                      (settings, Ids::gradleToolchain,                      getUndoManager(), "clang"),\r
-          androidPluginVersion                 (settings, Ids::androidPluginVersion,                 getUndoManager(), "7.0.0"),\r
+          androidPluginVersion                 (settings, Ids::androidPluginVersion,                 getUndoManager(), "7.3.0"),\r
           AndroidExecutable                    (getAppSettings().getStoredPath (Ids::androidStudioExePath, TargetOS::getThisOS()).get().toString())\r
     {\r
         name = getDisplayName();\r
@@ -342,18 +354,46 @@ protected:
     }\r
 \r
 private:\r
+    void updateExternalReadPermission()\r
+    {\r
+        const auto needsExternalRead = getSettingString (Ids::androidExternalReadNeeded);\r
+        settings.removeProperty (Ids::androidExternalReadNeeded, nullptr);\r
+\r
+        if (needsExternalRead.isEmpty())\r
+            return;\r
+\r
+        androidReadMediaAudioPermission .setValue (needsExternalRead, nullptr);\r
+        androidReadMediaImagesPermission.setValue (needsExternalRead, nullptr);\r
+        androidReadMediaVideoPermission .setValue (needsExternalRead, nullptr);\r
+    }\r
+\r
+    void updateBluetoothPermission()\r
+    {\r
+        const auto needsBluetooth = getSettingString (Ids::androidBluetoothNeeded);\r
+        settings.removeProperty (Ids::androidBluetoothNeeded, nullptr);\r
+\r
+        if (needsBluetooth.isEmpty())\r
+            return;\r
+\r
+        androidBluetoothScanNeeded     .setValue (needsBluetooth, nullptr);\r
+        androidBluetoothAdvertiseNeeded.setValue (needsBluetooth, nullptr);\r
+        androidBluetoothConnectNeeded  .setValue (needsBluetooth, nullptr);\r
+    }\r
+\r
     void writeCmakeFile (const File& file) const\r
     {\r
         build_tools::writeStreamToFile (file, [&] (MemoryOutputStream& mo)\r
         {\r
             mo.setNewLineString (getNewLineString());\r
 \r
-            mo << "# Automatically generated makefile, created by the Projucer" << newLine\r
+            mo << "# Automatically generated CMakeLists, created by the Projucer" << newLine\r
                << "# Don't edit this file! Your changes will be overwritten when you re-save the Projucer project!" << newLine\r
+               << newLine\r
+               << "cmake_minimum_required(VERSION 3.4.1)" << newLine\r
+               << newLine\r
+               << "project(juce_jni_project)" << newLine\r
                << newLine;\r
 \r
-            mo << "cmake_minimum_required(VERSION 3.4.1)" << newLine << newLine;\r
-\r
             if (! isLibrary())\r
                 mo << "set(BINARY_NAME \"juce_jni\")" << newLine << newLine;\r
 \r
@@ -405,13 +445,6 @@ private:
                 mo << ")" << newLine << newLine;\r
             }\r
 \r
-            auto cfgExtraLinkerFlags = getExtraLinkerFlagsString();\r
-            if (cfgExtraLinkerFlags.isNotEmpty())\r
-            {\r
-                mo << "set( JUCE_LDFLAGS \"" << cfgExtraLinkerFlags.replace ("\"", "\\\"") << "\")" << newLine;\r
-                mo << "set( CMAKE_SHARED_LINKER_FLAGS  \"${CMAKE_EXE_LINKER_FLAGS} ${JUCE_LDFLAGS}\")" << newLine << newLine;\r
-            }\r
-\r
             mo << "enable_language(ASM)" << newLine << newLine;\r
 \r
             const auto userLibraries = getUserLibraries();\r
@@ -455,6 +488,14 @@ private:
                     if (cfgDefines.size() > 0)\r
                         mo << "    add_definitions(" << getEscapedPreprocessorDefs (cfgDefines).joinIntoString (" ") << ")" << newLine;\r
 \r
+                    const auto cfgExtraLinkerFlags = cfg.getAllLinkerFlagsString();\r
+\r
+                    if (cfgExtraLinkerFlags.isNotEmpty())\r
+                    {\r
+                        mo << "    set( JUCE_LDFLAGS \"" << cfgExtraLinkerFlags.replace ("\"", "\\\"") << "\" )"       << newLine\r
+                           << "    set( CMAKE_SHARED_LINKER_FLAGS  \"${CMAKE_SHARED_LINKER_FLAGS} ${JUCE_LDFLAGS}\" )" << newLine << newLine;\r
+                    }\r
+\r
                     writeCmakePathLines (mo, "    ", "include_directories( AFTER", cfgHeaderPaths);\r
 \r
                     if (userLibraries.size() > 0)\r
@@ -535,26 +576,27 @@ private:
                 mo << newLine;\r
             }\r
 \r
-            auto flags = getProjectCompilerFlags();\r
-\r
-            if (flags.size() > 0)\r
-                mo << "target_compile_options( ${BINARY_NAME} PRIVATE " << flags.joinIntoString (" ") << " )" << newLine << newLine;\r
-\r
             for (ConstConfigIterator config (*this); config.next();)\r
             {\r
                 auto& cfg = dynamic_cast<const AndroidBuildConfiguration&> (*config);\r
 \r
-                mo << "if( JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg.getProductFlavourCMakeIdentifier() << "\" )" << newLine;\r
-                mo << "    target_compile_options( ${BINARY_NAME} PRIVATE";\r
+                mo << "if( JUCE_BUILD_CONFIGURATION MATCHES \"" << cfg.getProductFlavourCMakeIdentifier() << "\" )" << newLine\r
+                   << "    target_compile_options( ${BINARY_NAME} PRIVATE";\r
 \r
-                auto recommendedFlags = cfg.getRecommendedCompilerWarningFlags();\r
+                const auto recommendedFlags = cfg.getRecommendedCompilerWarningFlags();\r
 \r
                 for (auto& recommendedFlagsType : { recommendedFlags.common, recommendedFlags.cpp })\r
                     for (auto& flag : recommendedFlagsType)\r
                         mo << " " << flag;\r
 \r
-                mo << ")" << newLine;\r
-                mo << "endif()" << newLine << newLine;\r
+                const auto flags = getConfigCompilerFlags (cfg);\r
+\r
+                if (! flags.isEmpty())\r
+                    mo << " " << flags.joinIntoString (" ");\r
+\r
+                mo << " )"      << newLine\r
+                   << "endif()" << newLine\r
+                   <<              newLine;\r
             }\r
 \r
             auto libraries = getAndroidLibraries();\r
@@ -638,6 +680,7 @@ private:
 \r
         mo << "android {"                                                                    << newLine;\r
         mo << "    compileSdkVersion " << static_cast<int> (androidTargetSDK.get())          << newLine;\r
+        mo << "    namespace " << project.getBundleIdentifierString().toLowerCase().quoted() << newLine;\r
         mo << "    externalNativeBuild {"                                                    << newLine;\r
         mo << "        cmake {"                                                              << newLine;\r
         mo << "            path \"CMakeLists.txt\""                                          << newLine;\r
@@ -677,32 +720,25 @@ private:
 \r
             if (cfg.getArchitectures().isNotEmpty())\r
             {\r
-                mo << "            ndk {" << newLine;\r
-                mo << "                abiFilters " << toGradleList (StringArray::fromTokens (cfg.getArchitectures(),  " ", "")) << newLine;\r
-                mo << "            }" << newLine;\r
+                mo << "            ndk {" << newLine\r
+                   << "                abiFilters " << toGradleList (StringArray::fromTokens (cfg.getArchitectures(),  " ", "")) << newLine\r
+                   << "            }" << newLine;\r
             }\r
 \r
-            mo << "            externalNativeBuild {" << newLine;\r
-            mo << "                cmake {"           << newLine;\r
+            mo << "            externalNativeBuild {" << newLine\r
+               << "                cmake {"           << newLine;\r
 \r
             if (getProject().getProjectType().isStaticLibrary())\r
                 mo << "                    targets \"" << getNativeModuleBinaryName (cfg) << "\"" << newLine;\r
 \r
-            mo << "                    arguments "\r
-               << "\"-DJUCE_BUILD_CONFIGURATION=" << cfg.getProductFlavourCMakeIdentifier() << "\"";\r
-\r
-            mo << ", \"-DCMAKE_CXX_FLAGS_" << (cfg.isDebug() ? "DEBUG" : "RELEASE")\r
-               << "=-O" << cfg.getGCCOptimisationFlag();\r
-\r
-            mo << "\""\r
-               << ", \"-DCMAKE_C_FLAGS_"   << (cfg.isDebug() ? "DEBUG" : "RELEASE")\r
-               << "=-O" << cfg.getGCCOptimisationFlag()\r
-               << "\"" << newLine;\r
-\r
-            mo << "                }"                   << newLine;\r
-            mo << "            }"                       << newLine << newLine;\r
-            mo << "            dimension \"default\""   << newLine;\r
-            mo << "       }"                            << newLine;\r
+            mo << "                    cFlags    \"-O" << cfg.getGCCOptimisationFlag() << "\""                                      << newLine\r
+               << "                    cppFlags  \"-O" << cfg.getGCCOptimisationFlag() << "\""                                      << newLine\r
+               << "                    arguments \"-DJUCE_BUILD_CONFIGURATION=" << cfg.getProductFlavourCMakeIdentifier() << "\""   << newLine\r
+               << "                }"                                                                                               << newLine\r
+               << "            }"                                                                                                   << newLine\r
+                                                                                                                                    << newLine\r
+               << "            dimension \"default\""                                                                               << newLine\r
+               << "        }"                                                                                                       << newLine;\r
         }\r
 \r
         mo << "    }" << newLine;\r
@@ -1102,11 +1138,23 @@ private:
         props.add (new ChoicePropertyComponent (androidCameraNeeded, "Camera Required"),\r
                    "If enabled, this will set the android.permission.CAMERA flag in the manifest.");\r
 \r
-        props.add (new ChoicePropertyComponent (androidBluetoothNeeded, "Bluetooth Permissions Required"),\r
-                   "If enabled, this will set the android.permission.BLUETOOTH and  android.permission.BLUETOOTH_ADMIN flag in the manifest. This is required for Bluetooth MIDI on Android.");\r
+        props.add (new ChoicePropertyComponent (androidBluetoothScanNeeded, "Bluetooth Scan Required"),\r
+                   "If enabled, this will set the android.permission.BLUETOOTH_SCAN, android.permission.BLUETOOTH and android.permission.BLUETOOTH_ADMIN flags in the manifest. This is required for Bluetooth MIDI on Android.");\r
 \r
-        props.add (new ChoicePropertyComponent (androidExternalReadPermission, "Read From External Storage"),\r
-                   "If enabled, this will set the android.permission.READ_EXTERNAL_STORAGE flag in the manifest.");\r
+        props.add (new ChoicePropertyComponent (androidBluetoothAdvertiseNeeded, "Bluetooth Advertise Required"),\r
+                   "If enabled, this will set the android.permission.BLUETOOTH_ADVERTISE, android.permission.BLUETOOTH and android.permission.BLUETOOTH_ADMIN flags in the manifest.");\r
+\r
+        props.add (new ChoicePropertyComponent (androidBluetoothConnectNeeded, "Bluetooth Connect Required"),\r
+                   "If enabled, this will set the android.permission.BLUETOOTH_CONNECT, android.permission.BLUETOOTH and android.permission.BLUETOOTH_ADMIN flags in the manifest. This is required for Bluetooth MIDI on Android.");\r
+\r
+        props.add (new ChoicePropertyComponent (androidReadMediaAudioPermission, "Read Audio From External Storage"),\r
+                   "If enabled, this will set the android.permission.READ_MEDIA_AUDIO and android.permission.READ_EXTERNAL_STORAGE flags in the manifest.");\r
+\r
+        props.add (new ChoicePropertyComponent (androidReadMediaImagesPermission, "Read Images From External Storage"),\r
+                   "If enabled, this will set the android.permission.READ_MEDIA_IMAGES and android.permission.READ_EXTERNAL_STORAGE flags in the manifest.");\r
+\r
+        props.add (new ChoicePropertyComponent (androidReadMediaVideoPermission, "Read Video From External Storage"),\r
+                   "If enabled, this will set the android.permission.READ_MEDIA_VIDEO and android.permission.READ_EXTERNAL_STORAGE flags in the manifest.");\r
 \r
         props.add (new ChoicePropertyComponent (androidExternalWritePermission, "Write to External Storage"),\r
                    "If enabled, this will set the android.permission.WRITE_EXTERNAL_STORAGE flag in the manifest.");\r
@@ -1376,8 +1424,10 @@ private:
     }\r
 \r
     //==============================================================================\r
-    void addCompileUnits (const Project::Item& projectItem, MemoryOutputStream& mo,\r
-                          Array<build_tools::RelativePath>& excludeFromBuild, Array<std::pair<build_tools::RelativePath, String>>& extraCompilerFlags) const\r
+    void addCompileUnits (const Project::Item& projectItem,\r
+                          MemoryOutputStream& mo,\r
+                          Array<build_tools::RelativePath>& excludeFromBuild,\r
+                          Array<std::pair<build_tools::RelativePath, String>>& extraCompilerFlags) const\r
     {\r
         if (projectItem.isGroup())\r
         {\r
@@ -1402,7 +1452,7 @@ private:
             }\r
             else\r
             {\r
-                auto extraFlags = compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString();\r
+                auto extraFlags = getCompilerFlagsForProjectItem (projectItem);\r
 \r
                 if (extraFlags.isNotEmpty())\r
                     extraCompilerFlags.add ({ file, extraFlags });\r
@@ -1410,7 +1460,8 @@ private:
         }\r
     }\r
 \r
-    void addCompileUnits (MemoryOutputStream& mo, Array<build_tools::RelativePath>& excludeFromBuild,\r
+    void addCompileUnits (MemoryOutputStream& mo,\r
+                          Array<build_tools::RelativePath>& excludeFromBuild,\r
                           Array<std::pair<build_tools::RelativePath, String>>& extraCompilerFlags) const\r
     {\r
         for (int i = 0; i < getAllGroups().size(); ++i)\r
@@ -1457,10 +1508,10 @@ private:
         return cFlags;\r
     }\r
 \r
-    StringArray getProjectCompilerFlags() const\r
+    StringArray getConfigCompilerFlags (const BuildConfiguration& config) const\r
     {\r
         auto cFlags = getAndroidCompilerFlags();\r
-        cFlags.addArray (getEscapedFlags (StringArray::fromTokens (getExtraCompilerFlagsString(), true)));\r
+        cFlags.addArray (getEscapedFlags (StringArray::fromTokens (config.getAllCompilerFlagsString(), true)));\r
         return cFlags;\r
     }\r
 \r
@@ -1641,7 +1692,6 @@ private:
         setAttributeIfNotPresent (*manifest, "xmlns:android", "http://schemas.android.com/apk/res/android");\r
         setAttributeIfNotPresent (*manifest, "android:versionCode", androidVersionCode.get());\r
         setAttributeIfNotPresent (*manifest, "android:versionName",  project.getVersionString());\r
-        setAttributeIfNotPresent (*manifest, "package", project.getBundleIdentifierString().toLowerCase());\r
 \r
         return manifest;\r
     }\r
@@ -1680,6 +1730,22 @@ private:
             // This permission only has an effect on SDK version 28 and lower\r
             if (permission == "android.permission.WRITE_EXTERNAL_STORAGE")\r
                 usesPermission->setAttribute ("android:maxSdkVersion", "28");\r
+\r
+            // https://developer.android.com/training/data-storage/shared/documents-files\r
+            // If the SDK version is <= 28, READ_EXTERNAL_STORAGE is required to access any\r
+            // media file, including files created by the current app.\r
+            // If the SDK version is <= 32, READ_EXTERNAL_STORAGE is required to access other\r
+            // apps' media files.\r
+            // This permission has no effect on later Android versions.\r
+            if (permission == "android.permission.READ_EXTERNAL_STORAGE")\r
+                usesPermission->setAttribute ("android:maxSdkVersion", "32");\r
+\r
+            // These permissions are obsoleted by new more fine-grained permissions in API level 31\r
+            if (permission == "android.permission.BLUETOOTH"\r
+                || permission == "android.permission.BLUETOOTH_ADMIN")\r
+            {\r
+                usesPermission->setAttribute ("android:maxSdkVersion", "30");\r
+            }\r
         }\r
     }\r
 \r
@@ -1734,10 +1800,9 @@ private:
         auto* act = getOrCreateChildWithName (application, "activity");\r
 \r
         setAttributeIfNotPresent (*act, "android:name", getActivityClassString());\r
-        setAttributeIfNotPresent (*act, "android:label", "@string/app_name");\r
 \r
         if (! act->hasAttribute ("android:configChanges"))\r
-            act->setAttribute ("android:configChanges", "keyboardHidden|orientation|screenSize");\r
+            act->setAttribute ("android:configChanges", "keyboard|keyboardHidden|orientation|screenSize|navigation");\r
 \r
         if (androidScreenOrientation.get() == "landscape")\r
         {\r
@@ -1838,7 +1903,18 @@ private:
         if (androidCameraNeeded.get())\r
             s.add ("android.permission.CAMERA");\r
 \r
-        if (androidBluetoothNeeded.get())\r
+        if (androidBluetoothScanNeeded.get())\r
+            s.add ("android.permission.BLUETOOTH_SCAN");\r
+\r
+        if (androidBluetoothAdvertiseNeeded.get())\r
+            s.add ("android.permission.BLUETOOTH_ADVERTISE");\r
+\r
+        if (androidBluetoothConnectNeeded.get())\r
+            s.add ("android.permission.BLUETOOTH_CONNECT");\r
+\r
+        if (   androidBluetoothScanNeeded.get()\r
+            || androidBluetoothAdvertiseNeeded.get()\r
+            || androidBluetoothConnectNeeded.get())\r
         {\r
             s.add ("android.permission.BLUETOOTH");\r
             s.add ("android.permission.BLUETOOTH_ADMIN");\r
@@ -1846,8 +1922,21 @@ private:
             s.add ("android.permission.ACCESS_COARSE_LOCATION");\r
         }\r
 \r
-        if (androidExternalReadPermission.get())\r
+        if (androidReadMediaAudioPermission.get())\r
+            s.add ("android.permission.READ_MEDIA_AUDIO");\r
+\r
+        if (androidReadMediaImagesPermission.get())\r
+            s.add ("android.permission.READ_MEDIA_IMAGES");\r
+\r
+        if (androidReadMediaVideoPermission.get())\r
+            s.add ("android.permission.READ_MEDIA_VIDEO");\r
+\r
+        if (   androidReadMediaAudioPermission.get()\r
+            || androidReadMediaImagesPermission.get()\r
+            || androidReadMediaVideoPermission.get())\r
+        {\r
             s.add ("android.permission.READ_EXTERNAL_STORAGE");\r
+        }\r
 \r
         if (androidExternalWritePermission.get())\r
             s.add ("android.permission.WRITE_EXTERNAL_STORAGE");\r
index f8359fb2ab9dadc39e27af6e2807e5893023b12d..8d1c04b31ff68360ef363dcb0f633b1edefba34a 100644 (file)
@@ -404,7 +404,7 @@ private:
         if (config.isDebug())\r
             flags.add ("-g");\r
 \r
-        flags.addTokens (replacePreprocessorTokens (config, getExtraCompilerFlagsString()).trim(),\r
+        flags.addTokens (replacePreprocessorTokens (config, config.getAllCompilerFlagsString()).trim(),\r
                          " \n", "\"'");\r
 \r
         if (config.exporter.isLinux())\r
@@ -445,7 +445,7 @@ private:
         if (config.isLinkTimeOptimisationEnabled())\r
             flags.add ("-flto");\r
 \r
-        flags.addTokens (replacePreprocessorTokens (config, getExtraLinkerFlagsString()).trim(), " \n", "\"'");\r
+        flags.addTokens (replacePreprocessorTokens (config, config.getAllLinkerFlagsString()).trim(), " \n", "\"'");\r
 \r
         if (config.exporter.isLinux())\r
         {\r
@@ -761,7 +761,7 @@ private:
 \r
             if (projectItem.shouldBeCompiled())\r
             {\r
-                auto extraCompilerFlags = compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString();\r
+                auto extraCompilerFlags = getCompilerFlagsForProjectItem (projectItem);\r
 \r
                 if (extraCompilerFlags.isNotEmpty())\r
                 {\r
index b5563705c11efc3dec2cc5edc8978f336c48e341..c7b85ea20987cab01e8c096f915ac3d7a5f8b297 100644 (file)
@@ -73,11 +73,21 @@ public:
     String getWindowsTargetPlatformVersion() const    { return targetPlatformVersion.get(); }\r
 \r
     //==============================================================================\r
-    void addToolsetProperty (PropertyListBuilder& props, const char** names, const var* values, int num)\r
+    void addToolsetProperty (PropertyListBuilder& props, std::initializer_list<const char*> valueStrings)\r
     {\r
-        props.add (new ChoicePropertyComponent (platformToolsetValue, "Platform Toolset",\r
-                                                StringArray (names, num), { values, num }),\r
-                   "Specifies the version of the platform toolset that will be used when building this project.");\r
+        StringArray names;\r
+        Array<var> values;\r
+\r
+        for (const auto& valueString : valueStrings)\r
+        {\r
+            names.add (valueString);\r
+            values.add (valueString);\r
+        }\r
+\r
+        props.add (new ChoicePropertyComponent (platformToolsetValue, "Platform Toolset", names, values),\r
+                   "Specifies the version of the platform toolset that will be used when building this project.\n"\r
+                   "In order to use the ClangCL toolset, you must first install the \"C++ Clang Tools for Windows\" "\r
+                   "package using the Visual Studio Installer.");\r
     }\r
 \r
     void create (const OwnedArray<LibraryModule>&) const override\r
@@ -161,7 +171,7 @@ public:
               multiProcessorCompilationValue (config, Ids::multiProcessorCompilation,  getUndoManager(), true),\r
               intermediatesPathValue         (config, Ids::intermediatesPath,          getUndoManager()),\r
               characterSetValue              (config, Ids::characterSet,               getUndoManager()),\r
-              architectureTypeValue          (config, Ids::winArchitecture,            getUndoManager(), get64BitArchName()),\r
+              architectureTypeValue          (config, Ids::winArchitecture,            getUndoManager(), getIntel64BitArchName()),\r
               fastMathValue                  (config, Ids::fastMath,                   getUndoManager()),\r
               debugInformationFormatValue    (config, Ids::debugInformationFormat,     getUndoManager(), isDebug() ? "ProgramDatabase" : "None"),\r
               pluginBinaryCopyStepValue      (config, Ids::enablePluginBinaryCopyStep, getUndoManager(), false),\r
@@ -191,8 +201,10 @@ public:
         String getUnityPluginBinaryLocationString() const { return unityPluginBinaryLocation.get(); }\r
         String getIntermediatesPathString() const         { return intermediatesPathValue.get(); }\r
         String getCharacterSetString() const              { return characterSetValue.get(); }\r
-        String get64BitArchName() const                   { return "x64"; }\r
-        String get32BitArchName() const                   { return "Win32"; }\r
+        String getIntel64BitArchName() const              { return "x64"; }\r
+        String getIntel32BitArchName() const              { return "Win32"; }\r
+        String getArm64BitArchName() const                { return "ARM64"; }\r
+        String getArm32BitArchName() const                { return "ARM"; }\r
         String getArchitectureString() const              { return architectureTypeValue.get(); }\r
         String getDebugInformationFormatString() const    { return debugInformationFormatValue.get(); }\r
 \r
@@ -201,14 +213,13 @@ public:
         bool shouldLinkIncremental() const                { return enableIncrementalLinkingValue.get(); }\r
         bool isUsingRuntimeLibDLL() const                 { return useRuntimeLibDLLValue.get(); }\r
         bool shouldUseMultiProcessorCompilation() const   { return multiProcessorCompilationValue.get(); }\r
-        bool is64Bit() const                              { return getArchitectureString() == get64BitArchName(); }\r
         bool isFastMathEnabled() const                    { return fastMathValue.get(); }\r
         bool isPluginBinaryCopyStepEnabled() const        { return pluginBinaryCopyStepValue.get(); }\r
 \r
         //==============================================================================\r
         String createMSVCConfigName() const\r
         {\r
-            return getName() + "|" + (is64Bit() ? "x64" : "Win32");\r
+            return getName() + "|" + getArchitectureString();\r
         }\r
 \r
         String getOutputFilename (const String& suffix,\r
@@ -235,10 +246,9 @@ public:
                 addVisualStudioPluginInstallPathProperties (props);\r
 \r
             props.add (new ChoicePropertyComponent (architectureTypeValue, "Architecture",\r
-                                                    { get32BitArchName(), get64BitArchName() },\r
-                                                    { get32BitArchName(), get64BitArchName() }),\r
-                       "Whether to use a 32-bit or 64-bit architecture.");\r
-\r
+                                                    { getIntel32BitArchName(), getIntel64BitArchName(), getArm32BitArchName(), getArm64BitArchName() },\r
+                                                    { getIntel32BitArchName(), getIntel64BitArchName(), getArm32BitArchName(), getArm64BitArchName() }),\r
+                       "Which Windows architecture to use.");\r
 \r
             props.add (new ChoicePropertyComponentWithEnablement (debugInformationFormatValue,\r
                                                                   isDebug() ? isDebugValue : generateDebugSymbolsValue,\r
@@ -374,13 +384,26 @@ public:
 \r
         void setPluginBinaryCopyLocationDefaults()\r
         {\r
-            vstBinaryLocation.setDefault  ((is64Bit() ? "%ProgramW6432%" : "%programfiles(x86)%") + String ("\\Steinberg\\Vstplugins"));\r
+            const auto [programsFolderPath, commonsFolderPath] = [&]() -> std::tuple<String, String>\r
+            {\r
+                static const std::map<String, std::tuple<String, String>> options\r
+                {\r
+                    { "Win32", { "%programfiles(x86)%", "%CommonProgramFiles(x86)%" } },\r
+                    { "x64",   { "%ProgramW6432%",      "%CommonProgramW6432%"      } },\r
+                    { "ARM",   { "%programfiles(arm)%", "%CommonProgramFiles(arm)%" } },\r
+                    { "ARM64", { "%ProgramW6432%",      "%CommonProgramW6432%"      } }\r
+                };\r
+\r
+                if (const auto iter = options.find (getArchitectureString()); iter != options.cend())\r
+                    return iter->second;\r
 \r
-            auto prefix = is64Bit() ? "%CommonProgramW6432%"\r
-                                    : "%CommonProgramFiles(x86)%";\r
+                jassertfalse;\r
+                return { "%programfiles%", "%CommonProgramFiles%" };\r
+            }();\r
 \r
-            vst3BinaryLocation.setDefault (prefix + String ("\\VST3"));\r
-            aaxBinaryLocation.setDefault  (prefix + String ("\\Avid\\Audio\\Plug-Ins"));\r
+            vstBinaryLocation.setDefault  (programsFolderPath + String ("\\Steinberg\\Vstplugins"));\r
+            vst3BinaryLocation.setDefault (commonsFolderPath + String ("\\VST3"));\r
+            aaxBinaryLocation.setDefault  (commonsFolderPath + String ("\\Avid\\Audio\\Plug-Ins"));\r
             lv2BinaryLocation.setDefault  ("%APPDATA%\\LV2");\r
         }\r
 \r
@@ -424,8 +447,7 @@ public:
                     auto* e = configsGroup->createNewChildElement ("ProjectConfiguration");\r
                     e->setAttribute ("Include", config.createMSVCConfigName());\r
                     e->createNewChildElement ("Configuration")->addTextElement (config.getName());\r
-                    e->createNewChildElement ("Platform")->addTextElement (config.is64Bit() ? config.get64BitArchName()\r
-                                                                                            : config.get32BitArchName());\r
+                    e->createNewChildElement ("Platform")->addTextElement (config.getArchitectureString());\r
                 }\r
             }\r
 \r
@@ -615,7 +637,8 @@ public:
                     if (config.isFastMathEnabled())\r
                         cl->createNewChildElement ("FloatingPointModel")->addTextElement ("Fast");\r
 \r
-                    auto extraFlags = getOwner().replacePreprocessorTokens (config, getOwner().getExtraCompilerFlagsString()).trim();\r
+                    auto extraFlags = getOwner().replacePreprocessorTokens (config, config.getAllCompilerFlagsString()).trim();\r
+\r
                     if (extraFlags.isNotEmpty())\r
                         cl->createNewChildElement ("AdditionalOptions")->addTextElement (extraFlags + " %(AdditionalOptions)");\r
 \r
@@ -651,7 +674,7 @@ public:
                     link->createNewChildElement ("ProgramDatabaseFile")->addTextElement (pdbFilename);\r
                     link->createNewChildElement ("SubSystem")->addTextElement (type == ConsoleApp || type == LV2TurtleProgram ? "Console" : "Windows");\r
 \r
-                    if (! config.is64Bit())\r
+                    if (config.getArchitectureString() == "Win32")\r
                         link->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");\r
 \r
                     if (isUsingEditAndContinue)\r
@@ -674,7 +697,7 @@ public:
                     if (additionalDependencies.isNotEmpty())\r
                         link->createNewChildElement ("AdditionalDependencies")->addTextElement (additionalDependencies);\r
 \r
-                    auto extraLinkerOptions = getOwner().getExtraLinkerFlagsString();\r
+                    auto extraLinkerOptions = config.getAllLinkerFlagsString();\r
                     if (extraLinkerOptions.isNotEmpty())\r
                         link->createNewChildElement ("AdditionalOptions")->addTextElement (getOwner().replacePreprocessorTokens (config, extraLinkerOptions).trim()\r
                                                                                            + " %(AdditionalOptions)");\r
@@ -716,7 +739,7 @@ public:
                                                                build_tools::RelativePath::buildTargetFolder).toWindowsStyle());\r
                 }\r
 \r
-                if (getTargetFileType() == staticLibrary && ! config.is64Bit())\r
+                if (getTargetFileType() == staticLibrary && config.getArchitectureString() == "Win32")\r
                 {\r
                     auto* lib = group->createNewChildElement ("Lib");\r
                     lib->createNewChildElement ("TargetMachine")->addTextElement ("MachineX86");\r
@@ -889,7 +912,7 @@ public:
 \r
                     if (projectItem.shouldBeCompiled())\r
                     {\r
-                        auto extraCompilerFlags = owner.compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get().toString();\r
+                        auto extraCompilerFlags = getOwner().getCompilerFlagsForProjectItem (projectItem);\r
 \r
                         if (shouldAddBigobjFlag (path))\r
                         {\r
@@ -1196,7 +1219,7 @@ public:
                 auto outputFilename = config.getOutputFilename (".aaxplugin", true, type);\r
                 auto bundleDir      = getOwner().getOutDirFile (config, outputFilename);\r
                 auto bundleContents = bundleDir + "\\Contents";\r
-                auto archDir        = bundleContents + String ("\\") + (config.is64Bit() ? "x64" : "Win32");\r
+                auto archDir        = bundleContents + String ("\\") + config.getArchitectureString();\r
                 auto executablePath = archDir + String ("\\") + outputFilename;\r
 \r
                 auto pkgScript = String ("copy /Y ") + getOutputFilePath (config).quoted() + String (" ") + executablePath.quoted() + String ("\r\ncall ")\r
@@ -1274,7 +1297,7 @@ public:
 \r
                 auto bundleDir      = getOwner().getOutDirFile (config, config.getOutputFilename (".aaxplugin", false, type));\r
                 auto bundleContents = bundleDir + "\\Contents";\r
-                auto archDir        = bundleContents + String ("\\") + (config.is64Bit() ? "x64" : "Win32");\r
+                auto archDir        = bundleContents + String ("\\") + config.getArchitectureString();\r
 \r
                 for (auto& folder : StringArray { bundleDir, bundleContents, archDir })\r
                     script += String ("if not exist \"") + folder + String ("\" mkdir \"") + folder + String ("\"\r\n");\r
@@ -1820,10 +1843,7 @@ public:
 \r
     void createExporterProperties (PropertyListBuilder& props) override\r
     {\r
-        static const char* toolsetNames[] = { "v140", "v140_xp", "v141", "v141_xp" };\r
-        const var toolsets[]              = { "v140", "v140_xp", "v141", "v141_xp" };\r
-        addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));\r
-\r
+        addToolsetProperty (props, { "v140", "v140_xp", "v141", "v141_xp" });\r
         MSVCProjectExporterBase::createExporterProperties (props);\r
     }\r
 \r
@@ -1865,10 +1885,7 @@ public:
 \r
     void createExporterProperties (PropertyListBuilder& props) override\r
     {\r
-        static const char* toolsetNames[] = { "v140", "v140_xp", "v141", "v141_xp", "v142" };\r
-        const var toolsets[]              = { "v140", "v140_xp", "v141", "v141_xp", "v142" };\r
-        addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));\r
-\r
+        addToolsetProperty (props, { "v140", "v140_xp", "v141", "v141_xp", "v142", "ClangCL" });\r
         MSVCProjectExporterBase::createExporterProperties (props);\r
     }\r
 \r
@@ -1910,10 +1927,7 @@ public:
 \r
     void createExporterProperties (PropertyListBuilder& props) override\r
     {\r
-        static const char* toolsetNames[] = { "v140", "v140_xp", "v141", "v141_xp", "v142", "v143" };\r
-        const var toolsets[]              = { "v140", "v140_xp", "v141", "v141_xp", "v142", "v143" };\r
-        addToolsetProperty (props, toolsetNames, toolsets, numElementsInArray (toolsets));\r
-\r
+        addToolsetProperty (props, { "v140", "v140_xp", "v141", "v141_xp", "v142", "v143", "ClangCL" });\r
         MSVCProjectExporterBase::createExporterProperties (props);\r
     }\r
 \r
index 563f18bebc95cdd0c7178088c9f110671f2163d2..f506f750213564844cbb52c79c5cf6ca930050b8 100644 (file)
@@ -218,7 +218,7 @@ public:
             }\r
             else if (type == LV2PlugIn)\r
             {\r
-                s.add ("JUCE_LV2DIR := " + targetName + ".lv2");\r
+                s.add ("JUCE_LV2DIR := " + escapeQuotesAndSpaces (targetName) + ".lv2");\r
                 targetName = "$(JUCE_LV2DIR)/" + targetName + ".so";\r
             }\r
             else if (type == LV2TurtleProgram)\r
@@ -228,6 +228,9 @@ public:
 \r
             s.add ("JUCE_TARGET_" + getTargetVarName() + String (" := ") + escapeQuotesAndSpaces (targetName));\r
 \r
+            if (type == LV2PlugIn)\r
+                s.add ("JUCE_LV2_FULL_PATH := $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_PLUGIN)");\r
+\r
             if (config.isPluginBinaryCopyStepEnabled()\r
                 && (type == VST3PlugIn || type == VSTPlugIn || type == UnityPlugIn || type == LV2PlugIn))\r
             {\r
@@ -251,7 +254,6 @@ public:
                 else if (type == LV2PlugIn)\r
                 {\r
                     s.add ("JUCE_LV2DESTDIR := " + config.getLV2BinaryLocationString());\r
-                    s.add ("JUCE_LV2_FULL_PATH := $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_PLUGIN)");\r
                     s.add (copyCmd + "$(JUCE_LV2DIR) $(JUCE_LV2DESTDIR)");\r
                 }\r
             }\r
@@ -275,32 +277,30 @@ public:
             return String (getName()).toUpperCase().replaceCharacter (L' ', L'_');\r
         }\r
 \r
-        void writeObjects (OutputStream& out, const Array<std::pair<File, String>>& filesToCompile) const\r
+        void writeObjects (OutputStream& out, const std::vector<std::pair<build_tools::RelativePath, String>>& filesToCompile) const\r
         {\r
             out << "OBJECTS_" + getTargetVarName() + String (" := \\") << newLine;\r
 \r
             for (auto& f : filesToCompile)\r
-                out << "  $(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor ({ f.first, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder }))\r
+                out << "  $(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor (f.first))\r
                     << " \\" << newLine;\r
 \r
             out << newLine;\r
         }\r
 \r
-        void addFiles (OutputStream& out, const Array<std::pair<File, String>>& filesToCompile)\r
+        void addFiles (OutputStream& out, const std::vector<std::pair<build_tools::RelativePath, String>>& filesToCompile)\r
         {\r
             auto cppflagsVarName = "JUCE_CPPFLAGS_" + getTargetVarName();\r
             auto cflagsVarName   = "JUCE_CFLAGS_"   + getTargetVarName();\r
 \r
-            for (auto& f : filesToCompile)\r
+            for (auto& [path, flags] : filesToCompile)\r
             {\r
-                build_tools::RelativePath relativePath (f.first, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder);\r
-\r
-                out << "$(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor (relativePath)) << ": " << escapeQuotesAndSpaces (relativePath.toUnixStyle()) << newLine\r
-                    << "\t-$(V_AT)mkdir -p $(JUCE_OBJDIR)"                                                                                            << newLine\r
-                    << "\t@echo \"Compiling " << relativePath.getFileName() << "\""                                                                   << newLine\r
-                    << (relativePath.hasFileExtension ("c;s;S") ? "\t$(V_AT)$(CC) $(JUCE_CFLAGS) " : "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) ")\r
+                out << "$(JUCE_OBJDIR)/" << escapeQuotesAndSpaces (owner.getObjectFileFor (path)) << ": " << escapeQuotesAndSpaces (path.toUnixStyle()) << newLine\r
+                    << "\t-$(V_AT)mkdir -p $(JUCE_OBJDIR)"                                                                                              << newLine\r
+                    << "\t@echo \"Compiling " << path.getFileName() << "\""                                                                             << newLine\r
+                    << (path.hasFileExtension ("c;s;S") ? "\t$(V_AT)$(CC) $(JUCE_CFLAGS) " : "\t$(V_AT)$(CXX) $(JUCE_CXXFLAGS) ")\r
                     << "$(" << cppflagsVarName << ") $(" << cflagsVarName << ")"\r
-                    << (f.second.isNotEmpty() ? " $(" + owner.getCompilerFlagSchemeVariableName (f.second) + ")" : "") << " -o \"$@\" -c \"$<\""      << newLine\r
+                    << (flags.isNotEmpty() ? " $(" + owner.getCompilerFlagSchemeVariableName (flags) + ")" : "") << " -o \"$@\" -c \"$<\""              << newLine\r
                     << newLine;\r
             }\r
         }\r
@@ -380,13 +380,11 @@ public:
 \r
             if (type == VST3PlugIn)\r
             {\r
-                out << "\t-$(V_AT)mkdir -p $(JUCE_VST3DESTDIR)" << newLine\r
-                    << "\t-$(V_AT)cp -R $(JUCE_COPYCMD_VST3)"   << newLine;\r
+                out << "\t-$(V_AT)[ ! \"$(JUCE_VST3DESTDIR)\" ] || (mkdir -p $(JUCE_VST3DESTDIR) && cp -R $(JUCE_COPYCMD_VST3))" << newLine;\r
             }\r
             else if (type == VSTPlugIn)\r
             {\r
-                out << "\t-$(V_AT)mkdir -p $(JUCE_VSTDESTDIR)" << newLine\r
-                    << "\t-$(V_AT)cp -R $(JUCE_COPYCMD_VST)"   << newLine;\r
+                out << "\t-$(V_AT)[ ! \"$(JUCE_VSTDESTDIR)\" ]  || (mkdir -p $(JUCE_VSTDESTDIR)  && cp -R $(JUCE_COPYCMD_VST))"  << newLine;\r
             }\r
             else if (type == UnityPlugIn)\r
             {\r
@@ -397,15 +395,12 @@ public:
                                                       build_tools::RelativePath::projectFolder);\r
 \r
                 out << "\t-$(V_AT)cp " + scriptPath.toUnixStyle() + " $(JUCE_OUTDIR)/$(JUCE_UNITYDIR)" << newLine\r
-                    << "\t-$(V_AT)mkdir -p $(JUCE_UNITYDESTDIR)"                                       << newLine\r
-                    << "\t-$(V_AT)cp -R $(JUCE_COPYCMD_UNITY_PLUGIN)"                                  << newLine;\r
+                    << "\t-$(V_AT)[ ! \"$(JUCE_UNITYDESTDIR)\" ] || (mkdir -p $(JUCE_UNITYDESTDIR) && cp -R $(JUCE_COPYCMD_UNITY_PLUGIN))" << newLine;\r
             }\r
             else if (type == LV2PlugIn)\r
             {\r
-                out << "\t$(V_AT) $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_MANIFEST_HELPER) "\r
-                       "$(abspath $(JUCE_LV2_FULL_PATH))"                                              << newLine\r
-                    << "\t-$(V_AT)mkdir -p $(JUCE_LV2DESTDIR)"                                         << newLine\r
-                    << "\t-$(V_AT)cp -R $(JUCE_COPYCMD_LV2_PLUGIN)"                                    << newLine;\r
+                out << "\t$(V_AT) $(JUCE_OUTDIR)/$(JUCE_TARGET_LV2_MANIFEST_HELPER) $(JUCE_LV2_FULL_PATH)" << newLine\r
+                    << "\t-$(V_AT)[ ! \"$(JUCE_LV2DESTDIR)\" ] || (mkdir -p $(JUCE_LV2DESTDIR) && cp -R $(JUCE_COPYCMD_LV2_PLUGIN))" << newLine;\r
             }\r
 \r
             out << newLine;\r
@@ -651,7 +646,7 @@ private:
         for (auto& recommended : config.getRecommendedCompilerWarningFlags().common)\r
             result.add (recommended);\r
 \r
-        auto extra = replacePreprocessorTokens (config, getExtraCompilerFlagsString()).trim();\r
+        auto extra = replacePreprocessorTokens (config, config.getAllCompilerFlagsString()).trim();\r
 \r
         if (extra.isNotEmpty())\r
             result.add (extra);\r
@@ -722,7 +717,7 @@ private:
         if (config.isLinkTimeOptimisationEnabled())\r
             result.add ("-flto");\r
 \r
-        auto extraFlags = getExtraLinkerFlagsString().trim();\r
+        const auto extraFlags = config.getAllLinkerFlagsString().trim();\r
 \r
         if (extraFlags.isNotEmpty())\r
             result.add (replacePreprocessorTokens (config, extraFlags));\r
@@ -915,12 +910,19 @@ private:
 \r
     static String getCompilerFlagSchemeVariableName (const String& schemeName)   { return "JUCE_COMPILERFLAGSCHEME_" + schemeName; }\r
 \r
-    void findAllFilesToCompile (const Project::Item& projectItem, Array<std::pair<File, String>>& results) const\r
+    std::vector<std::pair<File, String>> findAllFilesToCompile (const Project::Item& projectItem) const\r
     {\r
+        std::vector<std::pair<File, String>> results;\r
+\r
         if (projectItem.isGroup())\r
         {\r
             for (int i = 0; i < projectItem.getNumChildren(); ++i)\r
-                findAllFilesToCompile (projectItem.getChild (i), results);\r
+            {\r
+                auto inner = findAllFilesToCompile (projectItem.getChild (i));\r
+                results.insert (results.end(),\r
+                                std::make_move_iterator (inner.cbegin()),\r
+                                std::make_move_iterator (inner.cend()));\r
+            }\r
         }\r
         else\r
         {\r
@@ -931,33 +933,35 @@ private:
                 if (shouldFileBeCompiledByDefault (f))\r
                 {\r
                     auto scheme = projectItem.getCompilerFlagSchemeString();\r
-                    auto flags = compilerFlagSchemesMap[scheme].get().toString();\r
+                    auto flags = getCompilerFlagsForProjectItem (projectItem);\r
 \r
                     if (scheme.isNotEmpty() && flags.isNotEmpty())\r
-                        results.add ({ f, scheme });\r
+                        results.emplace_back (f, scheme);\r
                     else\r
-                        results.add ({ f, {} });\r
+                        results.emplace_back (f, String{});\r
                 }\r
             }\r
         }\r
+\r
+        return results;\r
     }\r
 \r
-    void writeCompilerFlagSchemes (OutputStream& out, const Array<std::pair<File, String>>& filesToCompile) const\r
+    void writeCompilerFlagSchemes (OutputStream& out, const std::vector<std::pair<File, String>>& filesToCompile) const\r
     {\r
-        StringArray schemesToWrite;\r
+        std::set<String> schemesToWrite;\r
 \r
-        for (auto& f : filesToCompile)\r
-            if (f.second.isNotEmpty())\r
-                schemesToWrite.addIfNotAlreadyThere (f.second);\r
+        for (const auto& pair : filesToCompile)\r
+            if (pair.second.isNotEmpty())\r
+                schemesToWrite.insert (pair.second);\r
 \r
-        if (! schemesToWrite.isEmpty())\r
-        {\r
-            for (auto& s : schemesToWrite)\r
-                out << getCompilerFlagSchemeVariableName (s) << " := "\r
-                    << compilerFlagSchemesMap[s].get().toString() << newLine;\r
+        if (schemesToWrite.empty())\r
+            return;\r
 \r
-            out << newLine;\r
-        }\r
+        for (const auto& s : schemesToWrite)\r
+            if (const auto flags = getCompilerFlagsForFileCompilerFlagScheme (s); flags.isNotEmpty())\r
+                out << getCompilerFlagSchemeVariableName (s) << " := " << flags << newLine;\r
+\r
+        out << newLine;\r
     }\r
 \r
     void writeMakefile (OutputStream& out) const\r
@@ -1004,27 +1008,44 @@ private:
         for (ConstConfigIterator config (*this); config.next();)\r
             writeConfig (out, dynamic_cast<const MakeBuildConfiguration&> (*config));\r
 \r
-        Array<std::pair<File, String>> filesToCompile;\r
+        std::vector<std::pair<File, String>> filesToCompile;\r
 \r
         for (int i = 0; i < getAllGroups().size(); ++i)\r
-            findAllFilesToCompile (getAllGroups().getReference (i), filesToCompile);\r
+        {\r
+            auto group = findAllFilesToCompile (getAllGroups().getReference (i));\r
+            filesToCompile.insert (filesToCompile.end(),\r
+                                   std::make_move_iterator (group.cbegin()),\r
+                                   std::make_move_iterator (group.cend()));\r
+        }\r
 \r
         writeCompilerFlagSchemes (out, filesToCompile);\r
 \r
-        auto getFilesForTarget = [this] (const Array<std::pair<File, String>>& files,\r
-                                         MakefileTarget* target,\r
-                                         const Project& p) -> Array<std::pair<File, String>>\r
+        const auto getFilesForTarget = [this] (const std::vector<std::pair<File, String>>& files,\r
+                                               MakefileTarget* target,\r
+                                               const Project& p)\r
         {\r
-            Array<std::pair<File, String>> targetFiles;\r
+            std::vector<std::pair<build_tools::RelativePath, String>> targetFiles;\r
 \r
             auto targetType = (p.isAudioPluginProject() ? target->type : MakefileTarget::SharedCodeTarget);\r
 \r
-            for (auto& f : files)\r
-                if (p.getTargetTypeFromFilePath (f.first, true) == targetType)\r
-                    targetFiles.add (f);\r
+            for (auto& [path, flags] : files)\r
+            {\r
+                if (p.getTargetTypeFromFilePath (path, true) == targetType)\r
+                {\r
+                    targetFiles.emplace_back (build_tools::RelativePath { path,\r
+                                                                          getTargetFolder(),\r
+                                                                          build_tools::RelativePath::buildTargetFolder },\r
+                                              flags);\r
+                }\r
+            }\r
 \r
             if (targetType == MakefileTarget::LV2TurtleProgram)\r
-                targetFiles.add ({ project.resolveFilename (getLV2TurtleDumpProgramSource().toUnixStyle()), {} });\r
+            {\r
+                targetFiles.emplace_back (getLV2TurtleDumpProgramSource().rebased (projectFolder,\r
+                                                                                   getTargetFolder(),\r
+                                                                                   build_tools::RelativePath::buildTargetFolder),\r
+                                          String{});\r
+            }\r
 \r
             return targetFiles;\r
         };\r
index 6344807c9c1fe8958eb9b72c4eab8604845345f7..3d29ce30eee45c7bb896927102fca7318e4e629e 100644 (file)
@@ -689,7 +689,7 @@ public:
                        "added separated by a semicolon. The App Groups Capability setting must be enabled for this setting to have any effect.");\r
 \r
         props.add (new ChoicePropertyComponent (keepCustomXcodeSchemesValue, "Keep Custom Xcode Schemes"),\r
-                   "Enable this to keep any Xcode schemes you have created for debugging or running, e.g. to launch a plug-in in"\r
+                   "Enable this to keep any Xcode schemes you have created for debugging or running, e.g. to launch a plug-in in "\r
                    "various hosts. If disabled, all schemes are replaced by a default set.");\r
 \r
         props.add (new ChoicePropertyComponent (useHeaderMapValue, "USE_HEADERMAP"),\r
@@ -807,10 +807,10 @@ protected:
             : BuildConfiguration (p, t, e),\r
               iOS (isIOS),\r
               macOSBaseSDK                 (config, Ids::macOSBaseSDK,                 getUndoManager()),\r
-              macOSDeploymentTarget        (config, Ids::macOSDeploymentTarget,        getUndoManager(), "10.11"),\r
+              macOSDeploymentTarget        (config, Ids::macOSDeploymentTarget,        getUndoManager(), "10.13"),\r
               macOSArchitecture            (config, Ids::osxArchitecture,              getUndoManager(), macOSArch_Default),\r
               iosBaseSDK                   (config, Ids::iosBaseSDK,                   getUndoManager()),\r
-              iosDeploymentTarget          (config, Ids::iosDeploymentTarget,          getUndoManager(), "9.3"),\r
+              iosDeploymentTarget          (config, Ids::iosDeploymentTarget,          getUndoManager(), "11.0"),\r
               customXcodeFlags             (config, Ids::customXcodeFlags,             getUndoManager()),\r
               plistPreprocessorDefinitions (config, Ids::plistPreprocessorDefinitions, getUndoManager()),\r
               codeSignIdentity             (config, Ids::codeSigningIdentity,          getUndoManager()),\r
@@ -859,7 +859,7 @@ protected:
                            "The version of the macOS SDK to link against." + sdkInfoString + "10.11.");\r
 \r
                 props.add (new TextPropertyComponent (macOSDeploymentTarget, "macOS Deployment Target", 8, false),\r
-                           "The minimum version of macOS to target." + sdkInfoString + "10.7.");\r
+                           "The minimum version of macOS to target." + sdkInfoString + "10.9.");\r
 \r
                 props.add (new ChoicePropertyComponent (macOSArchitecture, "macOS Architecture",\r
                                                         { "Native architecture of build machine", "Standard 32-bit",        "Standard 32/64-bit",     "Standard 64-bit" },\r
@@ -1048,7 +1048,7 @@ public:
     struct XcodeTarget : build_tools::ProjectType::Target\r
     {\r
         //==============================================================================\r
-        XcodeTarget (build_tools::ProjectType::Target::Type targetType, const XcodeProjectExporter& exporter)\r
+        XcodeTarget (Type targetType, const XcodeProjectExporter& exporter)\r
             : Target (targetType),\r
               owner (exporter)\r
         {\r
@@ -1614,9 +1614,10 @@ public:
             for (const auto& xcodeFlags : { XcodeWarningFlags { recommendedWarnings.common, "OTHER_CFLAGS" },\r
                                             XcodeWarningFlags { recommendedWarnings.cpp,    "OTHER_CPLUSPLUSFLAGS" } })\r
             {\r
-                auto flags = (xcodeFlags.flags.joinIntoString (" ")\r
-                                 + " " + owner.getExtraCompilerFlagsString()).trim();\r
-                flags = owner.replacePreprocessorTokens (config, flags);\r
+                const auto flags = owner.replacePreprocessorTokens (config,\r
+                                                                    (xcodeFlags.flags.joinIntoString (" ")\r
+                                                                     + " "\r
+                                                                     + config.getAllCompilerFlagsString()).trim());\r
 \r
                 if (flags.isNotEmpty())\r
                     s.set (xcodeFlags.variable, flags.quoted());\r
@@ -1680,11 +1681,9 @@ public:
             s.set ("GCC_VERSION", gccVersion);\r
             s.set ("CLANG_LINK_OBJC_RUNTIME", "NO");\r
 \r
-            auto codeSigningIdentity = owner.getCodeSigningIdentity (config);\r
-            s.set (owner.iOS ? "\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"" : "CODE_SIGN_IDENTITY",\r
-                   codeSigningIdentity.quoted());\r
+            owner.addCodeSigningIdentity (config, s);\r
 \r
-            if (codeSigningIdentity.isNotEmpty())\r
+            if (owner.getCodeSigningIdentity (config).isNotEmpty())\r
             {\r
                 s.set ("PROVISIONING_PROFILE_SPECIFIER", "\"\"");\r
 \r
@@ -1699,10 +1698,13 @@ public:
                 s.set ("CODE_SIGN_ENTITLEMENTS", getEntitlementsFilename().quoted());\r
 \r
             {\r
-                auto cppStandard = owner.project.getCppStandardString();\r
+                const auto cppStandard = [&]() -> String\r
+                {\r
+                    if (owner.project.getCppStandardString() == "latest")\r
+                        return owner.project.getLatestNumberedCppStandardString();\r
 \r
-                if (cppStandard == "latest")\r
-                    cppStandard = owner.project.getLatestNumberedCppStandardString();\r
+                    return owner.project.getCppStandardString();\r
+                }();\r
 \r
                 s.set ("CLANG_CXX_LANGUAGE_STANDARD", (String (owner.shouldUseGNUExtensions() ? "gnu++"\r
                                                                                               : "c++") + cppStandard).quoted());\r
@@ -1851,7 +1853,7 @@ public:
                     flags.add (getLinkerFlagForLib (l));\r
             }\r
 \r
-            flags.add (owner.replacePreprocessorTokens (config, owner.getExtraLinkerFlagsString()));\r
+            flags.add (owner.replacePreprocessorTokens (config, config.getAllLinkerFlagsString()));\r
             flags = getCleanedStringArray (flags);\r
         }\r
 \r
@@ -1968,11 +1970,15 @@ public:
             StringArray paths (owner.extraSearchPaths);\r
             paths.addArray (config.getHeaderSearchPaths());\r
 \r
-            if (owner.project.getEnabledModules().isModuleEnabled ("juce_audio_plugin_client"))\r
+            constexpr auto audioPluginClient = "juce_audio_plugin_client";\r
+\r
+            if (owner.project.getEnabledModules().isModuleEnabled (audioPluginClient))\r
             {\r
-                // Needed to compile .r files\r
-                paths.add (owner.getModuleFolderRelativeToProject ("juce_audio_plugin_client")\r
-                                .rebased (owner.projectFolder, owner.getTargetFolder(), build_tools::RelativePath::buildTargetFolder)\r
+                paths.add (owner.getModuleFolderRelativeToProject (audioPluginClient)\r
+                                .getChildFile ("AU")\r
+                                .rebased (owner.projectFolder,\r
+                                          owner.getTargetFolder(),\r
+                                          build_tools::RelativePath::buildTargetFolder)\r
                                 .toUnixStyle());\r
             }\r
 \r
@@ -2299,7 +2305,16 @@ private:
 \r
             if (target->type == XcodeTarget::LV2PlugIn)\r
             {\r
-                auto script = "set -e\n\"$CONFIGURATION_BUILD_DIR/../"\r
+                // When building LV2 plugins on Arm macs, we need to load and run the plugin bundle\r
+                // during a post-build step in order to generate the plugin's supporting files. Arm\r
+                // macs will only load shared libraries if they are signed, but Xcode runs its\r
+                // signing step after any post-build scripts. As a workaround, we check whether the\r
+                // plugin is signed and generate an adhoc certificate if necessary, before running\r
+                // the manifest-generator.\r
+                auto script = "set -e\n"\r
+                              "xcrun codesign --verify \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\" "\r
+                              "|| xcrun codesign -s - \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\"\n"\r
+                              "\"$CONFIGURATION_BUILD_DIR/../"\r
                             + Project::getLV2FileWriterName()\r
                             + "\" \"$CONFIGURATION_BUILD_DIR/$PRODUCT_NAME\"\n";\r
 \r
@@ -2516,6 +2531,13 @@ private:
         return config.getCodeSignIdentityString();\r
     }\r
 \r
+    void addCodeSigningIdentity (const XcodeBuildConfiguration& config, StringPairArray& result) const\r
+    {\r
+        if (const auto codeSigningIdentity = getCodeSigningIdentity (config); codeSigningIdentity.isNotEmpty())\r
+            result.set (iOS ? "\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"" : "CODE_SIGN_IDENTITY",\r
+                        codeSigningIdentity.quoted());\r
+    }\r
+\r
     StringPairArray getProjectSettings (const XcodeBuildConfiguration& config) const\r
     {\r
         StringPairArray s;\r
@@ -2566,8 +2588,7 @@ private:
                 s.set ("ONLY_ACTIVE_ARCH", "YES");\r
         }\r
 \r
-        s.set (iOS ? "\"CODE_SIGN_IDENTITY[sdk=iphoneos*]\"" : "CODE_SIGN_IDENTITY",\r
-               getCodeSigningIdentity (config).quoted());\r
+        addCodeSigningIdentity (config, s);\r
 \r
         if (iOS)\r
         {\r
@@ -3196,7 +3217,7 @@ private:
                 xcodeTarget = getTargetOfType (project.getTargetTypeFromFilePath (projectItem.getFile(), false));\r
 \r
             return addFile (FileOptions().withRelativePath (path)\r
-                                         .withCompilerFlags (compilerFlagSchemesMap[projectItem.getCompilerFlagSchemeString()].get())\r
+                                         .withCompilerFlags (getCompilerFlagsForProjectItem (projectItem))\r
                                          .withCompilationEnabled (projectItem.shouldBeCompiled())\r
                                          .withAddToBinaryResourcesEnabled (projectItem.shouldBeAddedToBinaryResources())\r
                                          .withAddToXcodeResourcesEnabled (projectItem.shouldBeAddedToXcodeResources())\r
index a1e08a5ed31b224cfd2f70fdb0e9e08823e13dc1..915e4d5bdaa319c18fff5d6d696eeba645365142 100644 (file)
@@ -245,7 +245,11 @@ void ProjectExporter::updateCompilerFlagValues()
     compilerFlagSchemesMap.clear();\r
 \r
     for (auto& scheme : project.getCompilerFlagSchemes())\r
-        compilerFlagSchemesMap.set (scheme, { settings, scheme, getUndoManager() });\r
+    {\r
+        compilerFlagSchemesMap.emplace (std::piecewise_construct,\r
+                                        std::forward_as_tuple (scheme),\r
+                                        std::forward_as_tuple (settings, scheme, getUndoManager()));\r
+    }\r
 }\r
 \r
 //==============================================================================\r
@@ -285,9 +289,11 @@ void ProjectExporter::createPropertyEditors (PropertyListBuilder& props)
                "Extra command-line flags to be passed to the compiler. This string can contain references to preprocessor definitions in the "\r
                "form ${NAME_OF_DEFINITION}, which will be replaced with their values.");\r
 \r
-    for (HashMap<String, ValueTreePropertyWithDefault>::Iterator i (compilerFlagSchemesMap); i.next();)\r
-        props.add (new TextPropertyComponent (compilerFlagSchemesMap.getReference (i.getKey()), "Compiler Flags for " + i.getKey().quoted(), 8192, false),\r
+    for (const auto& [key, property] : compilerFlagSchemesMap)\r
+    {\r
+        props.add (new TextPropertyComponent (property, "Compiler Flags for " + key.quoted(), 8192, false),\r
                    "The exporter-specific compiler flags that will be added to files using this scheme.");\r
+    }\r
 \r
     props.add (new TextPropertyComponent (extraLinkerFlagsValue, "Extra Linker Flags", 8192, true),\r
                "Extra command-line flags to be passed to the linker. You might want to use this for adding additional libraries. "\r
@@ -507,6 +513,19 @@ String ProjectExporter::replacePreprocessorTokens (const ProjectExporter::BuildC
                                                  sourceString);\r
 }\r
 \r
+String ProjectExporter::getCompilerFlagsForFileCompilerFlagScheme (StringRef schemeName) const\r
+{\r
+    if (const auto iter = compilerFlagSchemesMap.find (schemeName); iter != compilerFlagSchemesMap.cend())\r
+        return iter->second.get().toString();\r
+\r
+    return {};\r
+}\r
+\r
+String ProjectExporter::getCompilerFlagsForProjectItem (const Project::Item& item) const\r
+{\r
+    return getCompilerFlagsForFileCompilerFlagScheme (item.getCompilerFlagSchemeString());\r
+}\r
+\r
 void ProjectExporter::copyMainGroupFromProject()\r
 {\r
     jassert (itemGroups.size() == 0);\r
@@ -761,31 +780,6 @@ ProjectExporter::BuildConfiguration::Ptr ProjectExporter::getConfiguration (int
     return createBuildConfig (getConfigurations().getChild (index));\r
 }\r
 \r
-bool ProjectExporter::hasConfigurationNamed (const String& nameToFind) const\r
-{\r
-    auto configs = getConfigurations();\r
-    for (int i = configs.getNumChildren(); --i >= 0;)\r
-        if (configs.getChild(i) [Ids::name].toString() == nameToFind)\r
-            return true;\r
-\r
-    return false;\r
-}\r
-\r
-String ProjectExporter::getUniqueConfigName (String nm) const\r
-{\r
-    auto nameRoot = nm;\r
-    while (CharacterFunctions::isDigit (nameRoot.getLastCharacter()))\r
-        nameRoot = nameRoot.dropLastCharacters (1);\r
-\r
-    nameRoot = nameRoot.trim();\r
-\r
-    int suffix = 2;\r
-    while (hasConfigurationNamed (name))\r
-        nm = nameRoot + " " + String (suffix++);\r
-\r
-    return nm;\r
-}\r
-\r
 void ProjectExporter::addNewConfigurationFromExisting (const BuildConfiguration& configToCopy)\r
 {\r
     auto configs = getConfigurations();\r
@@ -894,33 +888,22 @@ ProjectExporter::BuildConfiguration::BuildConfiguration (Project& p, const Value
      librarySearchPathValue        (config, Ids::libraryPath,              getUndoManager()),\r
      userNotesValue                (config, Ids::userNotes,                getUndoManager()),\r
      usePrecompiledHeaderFileValue (config, Ids::usePrecompiledHeaderFile, getUndoManager(), false),\r
-     precompiledHeaderFileValue    (config, Ids::precompiledHeaderFile,    getUndoManager())\r
+     precompiledHeaderFileValue    (config, Ids::precompiledHeaderFile,    getUndoManager()),\r
+     configCompilerFlagsValue      (config, Ids::extraCompilerFlags,       getUndoManager()),\r
+     configLinkerFlagsValue        (config, Ids::extraLinkerFlags,         getUndoManager())\r
 {\r
     auto& llvmFlags = recommendedCompilerWarningFlags[CompilerNames::llvm] = BuildConfiguration::CompilerWarningFlags::getRecommendedForGCCAndLLVM();\r
-    llvmFlags.common.addArray ({\r
-        "-Wshorten-64-to-32", "-Wconversion", "-Wint-conversion",\r
-        "-Wconditional-uninitialized", "-Wconstant-conversion", "-Wbool-conversion",\r
-        "-Wextra-semi", "-Wshift-sign-overflow",\r
-        "-Wshadow-all", "-Wnullable-to-nonnull-conversion",\r
-        "-Wmissing-prototypes"\r
-    });\r
-    llvmFlags.cpp.addArray ({\r
-        "-Wunused-private-field", "-Winconsistent-missing-destructor-override"\r
-    });\r
-    llvmFlags.objc.addArray ({\r
-        "-Wunguarded-availability", "-Wunguarded-availability-new"\r
-    });\r
+    llvmFlags.common.addArray ({ "-Wshorten-64-to-32", "-Wconversion", "-Wint-conversion",\r
+                                 "-Wconditional-uninitialized", "-Wconstant-conversion", "-Wbool-conversion",\r
+                                 "-Wextra-semi", "-Wshift-sign-overflow",\r
+                                 "-Wshadow-all", "-Wnullable-to-nonnull-conversion",\r
+                                 "-Wmissing-prototypes" });\r
+    llvmFlags.cpp.addArray ({ "-Wunused-private-field", "-Winconsistent-missing-destructor-override" });\r
+    llvmFlags.objc.addArray ({ "-Wunguarded-availability", "-Wunguarded-availability-new" });\r
 \r
     auto& gccFlags = recommendedCompilerWarningFlags[CompilerNames::gcc] = BuildConfiguration::CompilerWarningFlags::getRecommendedForGCCAndLLVM();\r
-    gccFlags.common.addArray ({\r
-        "-Wextra", "-Wsign-compare", "-Wno-implicit-fallthrough", "-Wno-maybe-uninitialized",\r
-        "-Wredundant-decls", "-Wno-strict-overflow",\r
-        "-Wshadow"\r
-    });\r
-}\r
-\r
-ProjectExporter::BuildConfiguration::~BuildConfiguration()\r
-{\r
+    gccFlags.common.addArray ({ "-Wextra", "-Wsign-compare", "-Wno-implicit-fallthrough", "-Wno-maybe-uninitialized",\r
+                                "-Wredundant-decls", "-Wno-strict-overflow", "-Wshadow" });\r
 }\r
 \r
 String ProjectExporter::BuildConfiguration::getGCCOptimisationFlag() const\r
@@ -1007,6 +990,12 @@ void ProjectExporter::BuildConfiguration::createPropertyEditors (PropertyListBui
                "Extra preprocessor definitions. Use the form \"NAME1=value NAME2=value\", using whitespace, commas, or "\r
                "new-lines to separate the items - to include a space or comma in a definition, precede it with a backslash.");\r
 \r
+    props.add (new TextPropertyComponent (configCompilerFlagsValue, "Configuration-specific Compiler Flags", 8192, true),\r
+               "Compiler flags that are only to be used in this configuration.");\r
+\r
+    props.add (new TextPropertyComponent (configLinkerFlagsValue, "Configuration-specific Linker Flags", 8192, true),\r
+               "Linker flags that are only to be used in this configuration.");\r
+\r
     props.add (new ChoicePropertyComponent (linkTimeOptimisationValue, "Link-Time Optimisation"),\r
                "Enable this to perform link-time code optimisation. This is recommended for release builds.");\r
 \r
@@ -1038,28 +1027,6 @@ StringPairArray ProjectExporter::BuildConfiguration::getAllPreprocessorDefs() co
                                   parsePreprocessorDefs (getBuildConfigPreprocessorDefsString()));\r
 }\r
 \r
-StringPairArray ProjectExporter::BuildConfiguration::getUniquePreprocessorDefs() const\r
-{\r
-    auto perConfigurationDefs = parsePreprocessorDefs (getBuildConfigPreprocessorDefsString());\r
-    auto globalDefs = project.getPreprocessorDefs();\r
-\r
-    for (int i = 0; i < globalDefs.size(); ++i)\r
-    {\r
-        auto globalKey = globalDefs.getAllKeys()[i];\r
-\r
-        int idx = perConfigurationDefs.getAllKeys().indexOf (globalKey);\r
-        if (idx >= 0)\r
-        {\r
-            auto globalValue = globalDefs.getAllValues()[i];\r
-\r
-            if (globalValue == perConfigurationDefs.getAllValues()[idx])\r
-                perConfigurationDefs.remove (idx);\r
-        }\r
-    }\r
-\r
-    return perConfigurationDefs;\r
-}\r
-\r
 StringArray ProjectExporter::BuildConfiguration::getHeaderSearchPaths() const\r
 {\r
     return getSearchPathsFromString (getHeaderSearchPathString() + ';' + project.getHeaderSearchPathsString());\r
index a29ef6d4361861b5d5866f3e783105511e871d45..a25d1fe86b418d61e05cfbfdc3bc2de97bf7e241 100644 (file)
@@ -37,7 +37,6 @@ class ProjectExporter  : private Value::Listener
 {\r
 public:\r
     ProjectExporter (Project&, const ValueTree& settings);\r
-    virtual ~ProjectExporter() override = default;\r
 \r
     //==============================================================================\r
     struct ExporterTypeInfo\r
@@ -140,9 +139,6 @@ public:
     Value getTargetLocationValue()                        { return targetLocationValue.getPropertyAsValue(); }\r
     String getTargetLocationString() const                { return targetLocationValue.get(); }\r
 \r
-    String getExtraCompilerFlagsString() const            { return extraCompilerFlagsValue.get().toString().replaceCharacters ("\r\n", "  "); }\r
-    String getExtraLinkerFlagsString() const              { return extraLinkerFlagsValue.get().toString().replaceCharacters ("\r\n", "  "); }\r
-\r
     StringArray getExternalLibrariesStringArray() const   { return getSearchPathsFromString (externalLibrariesValue.get().toString()); }\r
     String getExternalLibrariesString() const             { return getExternalLibrariesStringArray().joinIntoString (";"); }\r
 \r
@@ -228,7 +224,6 @@ public:
     {\r
     public:\r
         BuildConfiguration (Project& project, const ValueTree& configNode, const ProjectExporter&);\r
-        ~BuildConfiguration();\r
 \r
         using Ptr = ReferenceCountedObjectPtr<BuildConfiguration>;\r
 \r
@@ -253,7 +248,6 @@ public:
 \r
         String getBuildConfigPreprocessorDefsString() const    { return ppDefinesValue.get(); }\r
         StringPairArray getAllPreprocessorDefs() const;        // includes inherited definitions\r
-        StringPairArray getUniquePreprocessorDefs() const;     // returns pre-processor definitions that are not already in the project pre-processor defs\r
 \r
         String getHeaderSearchPathString() const               { return headerSearchPathValue.get(); }\r
         StringArray getHeaderSearchPaths() const;\r
@@ -267,6 +261,9 @@ public:
         bool shouldUsePrecompiledHeaderFile() const            { return usePrecompiledHeaderFileValue.get(); }\r
         String getPrecompiledHeaderFileContent() const;\r
 \r
+        String getAllCompilerFlagsString() const               { return (exporter.extraCompilerFlagsValue.get().toString() + "  " + configCompilerFlagsValue.get().toString()).replaceCharacters ("\r\n", "  ").trim(); }\r
+        String getAllLinkerFlagsString() const                 { return (exporter.extraLinkerFlagsValue  .get().toString() + "  " + configLinkerFlagsValue  .get().toString()).replaceCharacters ("\r\n", "  ").trim(); }\r
+\r
         //==============================================================================\r
         Value getValue (const Identifier& nm)                  { return config.getPropertyAsValue (nm, getUndoManager()); }\r
         UndoManager* getUndoManager() const                    { return project.getUndoManagerFor (config); }\r
@@ -311,7 +308,7 @@ public:
     protected:\r
         ValueTreePropertyWithDefault isDebugValue, configNameValue, targetNameValue, targetBinaryPathValue, recommendedWarningsValue, optimisationLevelValue,\r
                                      linkTimeOptimisationValue, ppDefinesValue, headerSearchPathValue, librarySearchPathValue, userNotesValue,\r
-                                     usePrecompiledHeaderFileValue, precompiledHeaderFileValue;\r
+                                     usePrecompiledHeaderFileValue, precompiledHeaderFileValue, configCompilerFlagsValue, configLinkerFlagsValue;\r
 \r
     private:\r
         std::map<String, CompilerWarningFlags> recommendedCompilerWarningFlags;\r
@@ -321,8 +318,6 @@ public:
 \r
     void addNewConfigurationFromExisting (const BuildConfiguration& configToCopy);\r
     void addNewConfiguration (bool isDebugConfig);\r
-    bool hasConfigurationNamed (const String& name) const;\r
-    String getUniqueConfigName (String name) const;\r
 \r
     String getExternalLibraryFlags (const BuildConfiguration& config) const;\r
 \r
@@ -403,6 +398,9 @@ public:
         return false;\r
     }\r
 \r
+    String getCompilerFlagsForFileCompilerFlagScheme (StringRef) const;\r
+    String getCompilerFlagsForProjectItem (const Project::Item&) const;\r
+\r
 protected:\r
     //==============================================================================\r
     String name;\r
@@ -418,7 +416,6 @@ protected:
                                  userNotesValue, gnuExtensionsValue, bigIconValue, smallIconValue, extraPPDefsValue;\r
 \r
     Value projectCompilerFlagSchemesValue;\r
-    HashMap<String, ValueTreePropertyWithDefault> compilerFlagSchemesMap;\r
 \r
     mutable Array<Project::Item> itemGroups;\r
     Project::Item* modulesGroup = nullptr;\r
@@ -455,6 +452,9 @@ protected:
     }\r
 \r
 private:\r
+    //==============================================================================\r
+    std::map<String, ValueTreePropertyWithDefault> compilerFlagSchemesMap;\r
+\r
     //==============================================================================\r
     void valueChanged (Value&) override   { updateCompilerFlagValues(); }\r
     void updateCompilerFlagValues();\r
index 350d7c4155a4dff20bff76b499a7929f2bbf2f38..88800347539f01230df5b7685604aac07050cb02 100644 (file)
@@ -234,7 +234,13 @@ namespace Ids
     DECLARE_ID (androidGradleSettingsContent);\r
     DECLARE_ID (androidCustomStringXmlElements);\r
     DECLARE_ID (androidBluetoothNeeded);\r
+    DECLARE_ID (androidBluetoothScanNeeded);\r
+    DECLARE_ID (androidBluetoothAdvertiseNeeded);\r
+    DECLARE_ID (androidBluetoothConnectNeeded);\r
     DECLARE_ID (androidExternalReadNeeded);\r
+    DECLARE_ID (androidReadMediaAudioPermission);\r
+    DECLARE_ID (androidReadMediaImagesPermission);\r
+    DECLARE_ID (androidReadMediaVideoPermission);\r
     DECLARE_ID (androidExternalWriteNeeded);\r
     DECLARE_ID (androidInAppBilling);\r
     DECLARE_ID (androidVibratePermissionNeeded);\r
index 37e4e89592978e23b0c1afe6ab6171e5ab9149bf..8795a09201d36933e34edd6dfcf9b10d45735966 100644 (file)
@@ -296,7 +296,6 @@ struct TranslationHelpers
 \r
             const StringArray& originalKeys (originalStrings.getAllKeys());\r
             const StringArray& originalValues (originalStrings.getAllValues());\r
-            int numRemoved = 0;\r
 \r
             for (int i = preStrings.size(); --i >= 0;)\r
             {\r
@@ -304,7 +303,6 @@ struct TranslationHelpers
                 {\r
                     preStrings.remove (i);\r
                     postStrings.remove (i);\r
-                    ++numRemoved;\r
                 }\r
             }\r
 \r
index 88aa018f7f24f6cd1a6d56f15cfabdf92fafe4a4..ea203361c5b3b72a0ea79e59d05ba17726e429aa 100644 (file)
@@ -265,6 +265,9 @@ ValueTree PIPGenerator::createExporterChild (const Identifier& exporterIdentifie
         }\r
     }\r
 \r
+    if (exporterIdentifier.toString() == AndroidProjectExporter::getValueTreeTypeName())\r
+        exporter.setProperty (Ids::androidBluetoothNeeded, true, nullptr);\r
+\r
     {\r
         ValueTree configs (Ids::CONFIGURATIONS);\r
 \r
index eb8d904cf7b86fa90cc78a6a87195355b153de14..4a3e744fb22238f188a71882f3c36f8e477a4d2b 100644 (file)
@@ -108,7 +108,6 @@ protected:
 \r
 private:\r
     class ItemSelectionTimer;\r
-    friend class ItemSelectionTimer;\r
     std::unique_ptr<Timer> delayedSelectionTimer;\r
 \r
     void invokeShowDocument();\r
index 15cbc65e76f321dbcdee5d20ab2c30d4f81bcf9d..f3f064e06af9936263a843cc6acb541faf1cd76d 100644 (file)
@@ -58,7 +58,6 @@ public:
 \r
 private:\r
     struct DotButton;\r
-    friend struct DotButton;\r
 \r
     struct PageInfo\r
     {\r
index 2c7ebd710b9d019acd752050d780bd95299c47a6..5d735a95ff205c28080ba6a222634646369097f8 100644 (file)
@@ -39,12 +39,12 @@ ifeq ($(CONFIG),Debug)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DDEBUG=1" "-D_DEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_CONSOLEAPP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_CONSOLEAPP := UnitTestRunner
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -g -ggdb -O0 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
@@ -60,12 +60,12 @@ ifeq ($(CONFIG),Release)
     TARGET_ARCH := 
   endif
 
-  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70002" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
+  JUCE_CPPFLAGS := $(DEPFLAGS) "-DLINUX=1" "-DNDEBUG=1" "-DJUCE_DISPLAY_SPLASH_SCREEN=0" "-DJUCE_USE_DARK_SPLASH_SCREEN=1" "-DJUCE_PROJUCER_VERSION=0x70005" "-DJUCE_MODULE_AVAILABLE_juce_analytics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_devices=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_formats=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_processors=1" "-DJUCE_MODULE_AVAILABLE_juce_audio_utils=1" "-DJUCE_MODULE_AVAILABLE_juce_core=1" "-DJUCE_MODULE_AVAILABLE_juce_cryptography=1" "-DJUCE_MODULE_AVAILABLE_juce_data_structures=1" "-DJUCE_MODULE_AVAILABLE_juce_dsp=1" "-DJUCE_MODULE_AVAILABLE_juce_events=1" "-DJUCE_MODULE_AVAILABLE_juce_graphics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_basics=1" "-DJUCE_MODULE_AVAILABLE_juce_gui_extra=1" "-DJUCE_MODULE_AVAILABLE_juce_opengl=1" "-DJUCE_MODULE_AVAILABLE_juce_osc=1" "-DJUCE_MODULE_AVAILABLE_juce_product_unlocking=1" "-DJUCE_MODULE_AVAILABLE_juce_video=1" "-DJUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1" "-DJUCE_PLUGINHOST_VST3=1" "-DJUCE_PLUGINHOST_LV2=1" "-DJUCE_STRICT_REFCOUNTEDPOINTER=1" "-DJUCE_STANDALONE_APPLICATION=1" "-DJUCE_UNIT_TESTS=1" "-DJUCER_LINUX_MAKE_6D53C8B4=1" "-DJUCE_APP_VERSION=1.0.0" "-DJUCE_APP_VERSION_HEX=0x10000" $(shell $(PKG_CONFIG) --cflags alsa freetype2 libcurl webkit2gtk-4.0 gtk+-x11-3.0) -pthread -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd -I../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 -I../../../../modules/juce_audio_processors/format_types/LV2_SDK -I../../../../modules/juce_audio_processors/format_types/VST3_SDK -I../../JuceLibraryCode -I../../../../modules $(CPPFLAGS)
   JUCE_CPPFLAGS_CONSOLEAPP :=  "-DJucePlugin_Build_VST=0" "-DJucePlugin_Build_VST3=0" "-DJucePlugin_Build_AU=0" "-DJucePlugin_Build_AUv3=0" "-DJucePlugin_Build_AAX=0" "-DJucePlugin_Build_Standalone=0" "-DJucePlugin_Build_Unity=0" "-DJucePlugin_Build_LV2=0"
   JUCE_TARGET_CONSOLEAPP := UnitTestRunner
 
   JUCE_CFLAGS += $(JUCE_CPPFLAGS) $(TARGET_ARCH) -O3 $(CFLAGS)
-  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++14 $(CXXFLAGS)
+  JUCE_CXXFLAGS += $(JUCE_CFLAGS) -std=c++17 $(CXXFLAGS)
   JUCE_LDFLAGS += $(TARGET_ARCH) -L$(JUCE_BINDIR) -L$(JUCE_LIBDIR) $(shell $(PKG_CONFIG) --libs alsa freetype2 libcurl) -fvisibility=hidden -lrt -ldl -lpthread -lGL $(LDFLAGS)
 
   CLEANCMD = rm -rf $(JUCE_OUTDIR)/$(TARGET) $(JUCE_OBJDIR)
index 3d05bd8ea1e6a17b6dd46819dad345cd7308a3bd..ba35702c1115729422356253a9daa3c286a9e986 100644 (file)
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                962CC7E0A536C3F56DBE1F8F /* Release */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                DEAD_CODE_STRIPPING = YES;
                                        "NDEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_analytics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                );
                                INSTALL_PATH = "/usr/bin";
                                LLVM_LTO = YES;
-                               MACOSX_DEPLOYMENT_TARGET = 10.10;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                CLANG_WARN_SUSPICIOUS_MOVE = YES;
                                CLANG_WARN_UNREACHABLE_CODE = YES;
                                CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
-                               CODE_SIGN_IDENTITY = "";
                                DEBUG_INFORMATION_FORMAT = dwarf;
                                ENABLE_STRICT_OBJC_MSGSEND = YES;
                                ENABLE_TESTABILITY = NO;
                A81C9C5D3696F83D5E8CFE11 /* Debug */ = {
                        isa = XCBuildConfiguration;
                        buildSettings = {
-                               CLANG_CXX_LANGUAGE_STANDARD = "c++14";
+                               CLANG_CXX_LANGUAGE_STANDARD = "c++17";
                                CLANG_CXX_LIBRARY = "libc++";
                                CLANG_LINK_OBJC_RUNTIME = NO;
-                               CODE_SIGN_IDENTITY = "";
                                COMBINE_HIDPI_IMAGES = YES;
                                CONFIGURATION_BUILD_DIR = "$(PROJECT_DIR)/build/$(CONFIGURATION)";
                                COPY_PHASE_STRIP = NO;
                                        "DEBUG=1",
                                        "JUCE_DISPLAY_SPLASH_SCREEN=0",
                                        "JUCE_USE_DARK_SPLASH_SCREEN=1",
-                                       "JUCE_PROJUCER_VERSION=0x70002",
+                                       "JUCE_PROJUCER_VERSION=0x70005",
                                        "JUCE_MODULE_AVAILABLE_juce_analytics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_basics=1",
                                        "JUCE_MODULE_AVAILABLE_juce_audio_devices=1",
                                        "$(inherited)",
                                );
                                INSTALL_PATH = "/usr/bin";
-                               MACOSX_DEPLOYMENT_TARGET = 10.10;
+                               MACOSX_DEPLOYMENT_TARGET = 10.13;
                                MTL_HEADER_SEARCH_PATHS = "$(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lilv $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sratom $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord/src $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/sord $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/serd $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK/lv2 $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/LV2_SDK $(SRCROOT)/../../../../modules/juce_audio_processors/format_types/VST3_SDK $(SRCROOT)/../../JuceLibraryCode $(SRCROOT)/../../../../modules";
                                OTHER_CFLAGS = "-Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
                                OTHER_CPLUSPLUSFLAGS = "-Woverloaded-virtual -Wreorder -Wzero-as-null-pointer-constant -Wunused-private-field -Winconsistent-missing-destructor-override -Wall -Wstrict-aliasing -Wuninitialized -Wunused-parameter -Wswitch-enum -Wsign-conversion -Wsign-compare -Wunreachable-code -Wcast-align -Wno-ignored-qualifiers -Wshorten-64-to-32 -Wconversion -Wint-conversion -Wconditional-uninitialized -Wconstant-conversion -Wbool-conversion -Wextra-semi -Wshift-sign-overflow -Wshadow-all -Wnullable-to-nonnull-conversion -Wmissing-prototypes -Wunguarded-availability -Wunguarded-availability-new";
index 8c216b9fb3dbaa9d6a0b43cafbe419c25c079b31..beb5b01d27632b247b37033fd858186066d9fffb 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2017_78A5024=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index aaaf298f3ec8478a282429694a9519513ace1562..e0a95f8886b9d0c3810feca05654a060d2c1aac6 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <Filter>JUCE Modules\juce_analytics</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 9928fd8d93f9bed4ae099dc8571923f8e210e369..3f268eba698d975547d3534dbdacbf74f50f027b 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2019_78A5026=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index a60b3465dcc5286ac860da2c2176cea928767739..2d93b6b183664b166644a16e57fcf5067cb235be 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <Filter>JUCE Modules\juce_analytics</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index 20584fb47a60599473d9e0d38a4aa2b896e7e36e..5cde0f75a1e4d37f30a9aa6ad6f59a3a2e370c0e 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
       <AdditionalOptions>/w44265 /w45038 /w44062 %(AdditionalOptions)</AdditionalOptions>\r
       <TreatWarningAsError>true</TreatWarningAsError>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lilv;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sratom;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord\src;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\sord;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\serd;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK\lv2;..\..\..\..\modules\juce_audio_processors\format_types\LV2_SDK;..\..\..\..\modules\juce_audio_processors\format_types\VST3_SDK;..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;_CONSOLE;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_analytics=1;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_dsp=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_osc=1;JUCE_MODULE_AVAILABLE_juce_product_unlocking=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_PLUGINHOST_VST3=1;JUCE_PLUGINHOST_LV2=1;JUCE_STRICT_REFCOUNTEDPOINTER=1;JUCE_STANDALONE_APPLICATION=1;JUCE_UNIT_TESTS=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\UnitTestRunner.exe</OutputFile>\r
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index dfe10afe9c06fc5a581cab55a03b8f617383aeba..d785e613fb2f329bd19870f0d7daec650b57a521 100644 (file)
     <ClCompile Include="..\..\..\..\modules\juce_analytics\juce_analytics.cpp">\r
       <Filter>JUCE Modules\juce_analytics</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index b340c140acb92b208d114be6c1d23c070d923b83..9fc1ad3b45e6e72bb4d2a7a19e21d1a7f206a954 100644 (file)
   <EXPORTFORMATS>\r
     <XCODE_MAC targetFolder="Builds/MacOSX" applicationCategory="public.app-category.developer-tools">\r
       <CONFIGURATIONS>\r
-        <CONFIGURATION name="Debug" osxCompatibility="10.10 SDK" isDebug="1" targetName="UnitTestRunner"\r
-                       recommendedWarnings="LLVM" macOSDeploymentTarget="10.10"/>\r
-        <CONFIGURATION name="Release" osxCompatibility="10.10 SDK" isDebug="0" targetName="UnitTestRunner"\r
-                       recommendedWarnings="LLVM" macOSDeploymentTarget="10.10"/>\r
+        <CONFIGURATION name="Debug" isDebug="1" targetName="UnitTestRunner"\r
+                       recommendedWarnings="LLVM"/>\r
+        <CONFIGURATION name="Release" isDebug="0" targetName="UnitTestRunner"\r
+                       recommendedWarnings="LLVM"/>\r
       </CONFIGURATIONS>\r
       <MODULEPATHS>\r
         <MODULEPATH id="juce_core" path="../../modules"/>\r
index 42b8349d0999de4a7f08ebfb0605b40dbbe55a73..b08545b456053e409cce6d70b8946e5b8feea2df 100644 (file)
@@ -64,7 +64,7 @@
       <Optimization>Disabled</Optimization>\r
       <DebugInformationFormat>ProgramDatabase</DebugInformationFormat>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <WarningLevel>Level4</WarningLevel>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;DEBUG;_DEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\juce_dll.lib</OutputFile>\r
     <ClCompile>\r
       <Optimization>Full</Optimization>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
       <RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>\r
       <RuntimeTypeInfo>true</RuntimeTypeInfo>\r
       <PrecompiledHeader>NotUsing</PrecompiledHeader>\r
       <WarningLevel>Level4</WarningLevel>\r
       <SuppressStartupBanner>true</SuppressStartupBanner>\r
       <MultiProcessorCompilation>true</MultiProcessorCompilation>\r
-      <LanguageStandard>stdcpp14</LanguageStandard>\r
+      <LanguageStandard>stdcpp17</LanguageStandard>\r
     </ClCompile>\r
     <ResourceCompile>\r
       <AdditionalIncludeDirectories>..\..\JuceLibraryCode;..\..\..\..\modules;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>\r
-      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70002;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
+      <PreprocessorDefinitions>_CRT_SECURE_NO_WARNINGS;WIN32;_WINDOWS;NDEBUG;JUCE_DISPLAY_SPLASH_SCREEN=0;JUCE_USE_DARK_SPLASH_SCREEN=1;JUCE_PROJUCER_VERSION=0x70005;JUCE_MODULE_AVAILABLE_juce_audio_basics=1;JUCE_MODULE_AVAILABLE_juce_audio_devices=1;JUCE_MODULE_AVAILABLE_juce_audio_formats=1;JUCE_MODULE_AVAILABLE_juce_audio_processors=1;JUCE_MODULE_AVAILABLE_juce_audio_utils=1;JUCE_MODULE_AVAILABLE_juce_core=1;JUCE_MODULE_AVAILABLE_juce_cryptography=1;JUCE_MODULE_AVAILABLE_juce_data_structures=1;JUCE_MODULE_AVAILABLE_juce_events=1;JUCE_MODULE_AVAILABLE_juce_graphics=1;JUCE_MODULE_AVAILABLE_juce_gui_basics=1;JUCE_MODULE_AVAILABLE_juce_gui_extra=1;JUCE_MODULE_AVAILABLE_juce_opengl=1;JUCE_MODULE_AVAILABLE_juce_video=1;JUCE_GLOBAL_MODULE_SETTINGS_INCLUDED=1;JUCE_STANDALONE_APPLICATION=1;JUCE_DLL_BUILD=1;JUCER_VS2022_78A503E=1;JUCE_APP_VERSION=1.0.0;JUCE_APP_VERSION_HEX=0x10000;JucePlugin_Build_VST=0;JucePlugin_Build_VST3=0;JucePlugin_Build_AU=0;JucePlugin_Build_AUv3=0;JucePlugin_Build_AAX=0;JucePlugin_Build_Standalone=0;JucePlugin_Build_Unity=0;JucePlugin_Build_LV2=0;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions>\r
     </ResourceCompile>\r
     <Link>\r
       <OutputFile>$(OutDir)\juce_dll.lib</OutputFile>\r
     <Lib/>\r
   </ItemDefinitionGroup>\r
   <ItemGroup>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <ExcludedFromBuild>true</ExcludedFromBuild>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <ExcludedFromBuild>true</ExcludedFromBuild>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\ordinals.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_decoder.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h"/>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_stereo.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\floor\floor_books.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_intel_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_CFHelpers.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_SharedCode.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_win32_ComSmartPtr.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAValueProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_UIAWindowProvider.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_XWindowSystem.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_ScopedDPIAwarenessDisabler.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_win32_ScopedThreadDPIAwarenessSetter.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_ThreadWithProgressWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TooltipWindow.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h"/>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeDocument.h"/>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_extra\code_editor\juce_CodeEditorComponent.h"/>\r
index 473d86c6191715d97f9cbf7f23ecfcc6a4ebb2a3..33d4edb9ef64220761c6eb04571199919b5768f0 100644 (file)
     </Filter>\r
   </ItemGroup>\r
   <ItemGroup>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\audio_play_head\juce_AudioPlayHead.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\audio_play_head</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\buffers\juce_AudioChannelSet.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\buffers</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMP_test.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPIterator.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\midi\ump\juce_UMPMidi1ToMidi2DefaultTranslator.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\midi\ump</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_MixerAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_PositionableAudioSource.cpp">\r
+      <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_basics\sources\juce_ResamplingAudioSource.cpp">\r
       <Filter>JUCE Modules\juce_audio_basics\sources</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_RangedAudioParameter.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_audio_processors\utilities\juce_VSTCallbackHandler.cpp">\r
+      <Filter>JUCE Modules\juce_audio_processors\utilities</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_audio_processors\juce_audio_processors.cpp">\r
       <Filter>JUCE Modules\juce_audio_processors</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\app_properties\juce_PropertiesFile.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\app_properties</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoableAction.cpp">\r
+      <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_data_structures\undomanager\juce_UndoManager.cpp">\r
       <Filter>JUCE Modules\juce_data_structures\undomanager</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.cpp">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.cpp">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_SystemTrayIconComponent.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
     </ClCompile>\r
+    <ClCompile Include="..\..\..\..\modules\juce_gui_extra\misc\juce_WebBrowserComponent.cpp">\r
+      <Filter>JUCE Modules\juce_gui_extra\misc</Filter>\r
+    </ClCompile>\r
     <ClCompile Include="..\..\..\..\modules\juce_gui_extra\native\juce_android_PushNotifications.cpp">\r
       <Filter>JUCE Modules\juce_gui_extra\native</Filter>\r
     </ClCompile>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\stream_encoder.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
     </ClInclude>\r
-    <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\flac\win_utf8_io.h">\r
-      <Filter>JUCE Modules\juce_audio_formats\codecs\flac</Filter>\r
-    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled\res_books_51.h">\r
       <Filter>JUCE Modules\juce_audio_formats\codecs\oggvorbis\libvorbis-1.3.7\lib\books\coupled</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_mac_ObjCHelpers.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_native_ThreadPriorities.h">\r
+      <Filter>JUCE Modules\juce_core\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_core\native\juce_posix_IPAddress.h">\r
       <Filter>JUCE Modules\juce_core\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\accessibility\juce_win32_WindowsUIAWrapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\accessibility</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_ScopedWindowAssociation.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\x11\juce_linux_X11_Symbols.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native\x11</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_CGMetalLayerRenderer.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_mac_PerScreenDisplayLinks.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\native\juce_MultiTouchMapper.h">\r
       <Filter>JUCE Modules\juce_gui_basics\native</Filter>\r
     </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_TopLevelWindow.h">\r
       <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
     </ClInclude>\r
+    <ClInclude Include="..\..\..\..\modules\juce_gui_basics\windows\juce_VBlankAttachement.h">\r
+      <Filter>JUCE Modules\juce_gui_basics\windows</Filter>\r
+    </ClInclude>\r
     <ClInclude Include="..\..\..\..\modules\juce_gui_basics\juce_gui_basics.h">\r
       <Filter>JUCE Modules\juce_gui_basics</Filter>\r
     </ClInclude>\r
index a51590ccfaf0b7ff745ecf6c677c7da6df38795d..68330694c39afce09636314a5294e8a508357273 100644 (file)
@@ -44,5 +44,3 @@ juce_add_modules(
     juce_osc
     juce_product_unlocking
     juce_video)
-
-add_subdirectory(juce_audio_plugin_client)
index 42eae71cbb0a64c0e5fbb917b43c867524cd2221..745371f530399d6e685778e0fd43452d5aa74e70 100644 (file)
 \r
   ID:                 juce_analytics\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE analytics classes\r
   description:        Classes to collect analytics and send to destinations\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_gui_basics\r
 \r
diff --git a/modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp b/modules/juce_audio_basics/audio_play_head/juce_AudioPlayHead.cpp
new file mode 100644 (file)
index 0000000..72888e2
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   The code included in this file is provided under the terms of the ISC license\r
+   http://www.isc.org/downloads/software-support-policy/isc-license. Permission\r
+   To use, copy, modify, and/or distribute this software for any purpose with or\r
+   without fee is hereby granted provided that the above copyright notice and\r
+   this permission notice appear in all copies.\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+bool AudioPlayHead::canControlTransport()                                          { return false; }\r
+void AudioPlayHead::transportPlay ([[maybe_unused]] bool shouldStartPlaying)       {}\r
+void AudioPlayHead::transportRecord ([[maybe_unused]] bool shouldStartRecording)   {}\r
+void AudioPlayHead::transportRewind()                                              {}\r
+\r
+} // namespace juce\r
index 51907c327ad0f5be6b94fdccea456b3f617d69ee..3c47f85cb1e026207582f10e4003d18158f19945 100644 (file)
@@ -102,13 +102,13 @@ public:
         double getEffectiveRate() const                 { return pulldown ? (double) base / 1.001 : (double) base; }\r
 \r
         /** Returns a copy of this object with the specified base rate. */\r
-        JUCE_NODISCARD FrameRate withBaseRate (int x) const            { return with (&FrameRate::base, x); }\r
+        [[nodiscard]] FrameRate withBaseRate (int x) const            { return with (&FrameRate::base, x); }\r
 \r
         /** Returns a copy of this object with drop frames enabled or disabled, as specified. */\r
-        JUCE_NODISCARD FrameRate withDrop (bool x = true) const        { return with (&FrameRate::drop, x); }\r
+        [[nodiscard]] FrameRate withDrop (bool x = true) const        { return with (&FrameRate::drop, x); }\r
 \r
         /** Returns a copy of this object with pulldown enabled or disabled, as specified. */\r
-        JUCE_NODISCARD FrameRate withPullDown (bool x = true) const    { return with (&FrameRate::pulldown, x); }\r
+        [[nodiscard]] FrameRate withPullDown (bool x = true) const    { return with (&FrameRate::pulldown, x); }\r
 \r
         /** Returns true if this instance is equal to other. */\r
         bool operator== (const FrameRate& other) const\r
@@ -578,16 +578,16 @@ public:
     virtual Optional<PositionInfo> getPosition() const = 0;\r
 \r
     /** Returns true if this object can control the transport. */\r
-    virtual bool canControlTransport()                         { return false; }\r
+    virtual bool canControlTransport();\r
 \r
     /** Starts or stops the audio. */\r
-    virtual void transportPlay (bool shouldStartPlaying)       { ignoreUnused (shouldStartPlaying); }\r
+    virtual void transportPlay (bool shouldStartPlaying);\r
 \r
     /** Starts or stops recording the audio. */\r
-    virtual void transportRecord (bool shouldStartRecording)   { ignoreUnused (shouldStartRecording); }\r
+    virtual void transportRecord (bool shouldStartRecording);\r
 \r
     /** Rewinds the audio. */\r
-    virtual void transportRewind()                             {}\r
+    virtual void transportRewind();\r
 };\r
 \r
 } // namespace juce\r
index aca7d7ce28e704b40a625c07cb3c6e63ebf99ee3..c59074475d8243691e79388d4cba6ca57b4d9126 100644 (file)
@@ -436,6 +436,9 @@ public:
         /** Adds a number of samples to the pointer's position. */\r
         Pointer& operator+= (int samplesToJump) noexcept        { this->advanceDataBy (data, samplesToJump); return *this; }\r
 \r
+        /** Returns a new pointer with the specified offset from this pointer's position. */\r
+        Pointer operator+ (int samplesToJump) const             { return Pointer { *this } += samplesToJump; }\r
+\r
         /** Writes a stream of samples into this pointer from another pointer.\r
             This will copy the specified number of samples, converting between formats appropriately.\r
         */\r
@@ -662,7 +665,7 @@ private:
     {\r
         using ElementType = std::remove_pointer_t<decltype (DataFormat::data)>;\r
         using ChannelType = std::conditional_t<IsConst, const ElementType*, ElementType*>;\r
-        using DataType = std::conditional_t<IsInterleaved, ChannelType, ChannelType*>;\r
+        using DataType = std::conditional_t<IsInterleaved, ChannelType, ChannelType const*>;\r
         using PointerType = Pointer<DataFormat,\r
                                     Endianness,\r
                                     std::conditional_t<IsInterleaved, Interleaved, NonInterleaved>,\r
index 9ea81f51df4da9ee1c168fd8cc2bcebf810e0f74..d583a59399aff1831c248ea6c27512109e685c7b 100644 (file)
@@ -324,7 +324,7 @@ public:
         Don't modify any of the pointers that are returned, and bear in mind that\r
         these will become invalid if the buffer is resized.\r
     */\r
-    const Type** getArrayOfReadPointers() const noexcept            { return const_cast<const Type**> (channels); }\r
+    const Type* const* getArrayOfReadPointers() const noexcept            { return channels; }\r
 \r
     /** Returns an array of pointers to the channels in the buffer.\r
 \r
@@ -339,7 +339,7 @@ public:
 \r
         @see setNotClear\r
     */\r
-    Type** getArrayOfWritePointers() noexcept                       { isClear = false; return channels; }\r
+    Type* const* getArrayOfWritePointers() noexcept                       { isClear = false; return channels; }\r
 \r
     //==============================================================================\r
     /** Changes the buffer's size or number of channels.\r
@@ -465,7 +465,7 @@ public:
         @param newNumSamples    the number of samples to use - this must correspond to the\r
                                 size of the arrays passed in\r
     */\r
-    void setDataToReferTo (Type** dataToReferTo,\r
+    void setDataToReferTo (Type* const* dataToReferTo,\r
                            int newNumChannels,\r
                            int newStartSample,\r
                            int newNumSamples)\r
@@ -506,7 +506,7 @@ public:
         @param newNumSamples    the number of samples to use - this must correspond to the\r
                                 size of the arrays passed in\r
     */\r
-    void setDataToReferTo (Type** dataToReferTo,\r
+    void setDataToReferTo (Type* const* dataToReferTo,\r
                            int newNumChannels,\r
                            int newNumSamples)\r
     {\r
@@ -558,7 +558,11 @@ public:
         if (! isClear)\r
         {\r
             for (int i = 0; i < numChannels; ++i)\r
+            {\r
+                JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4661)\r
                 FloatVectorOperations::clear (channels[i], size);\r
+                JUCE_END_IGNORE_WARNINGS_MSVC\r
+            }\r
 \r
             isClear = true;\r
         }\r
@@ -799,6 +803,8 @@ public:
             auto* d = channels[destChannel] + destStartSample;\r
             auto* s = source.channels[sourceChannel] + sourceStartSample;\r
 \r
+            JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4661)\r
+\r
             if (isClear)\r
             {\r
                 isClear = false;\r
@@ -815,6 +821,8 @@ public:
                 else\r
                     FloatVectorOperations::add (d, s, numSamples);\r
             }\r
+\r
+            JUCE_END_IGNORE_WARNINGS_MSVC\r
         }\r
     }\r
 \r
@@ -877,7 +885,11 @@ public:
         @param numSamples           the number of samples to process\r
         @param startGain            the gain to apply to the first sample (this is multiplied with\r
                                     the source samples before they are added to this buffer)\r
-        @param endGain              the gain to apply to the final sample. The gain is linearly\r
+        @param endGain              The gain that would apply to the sample after the final sample.\r
+                                    The gain that applies to the final sample is\r
+                                    (numSamples - 1) / numSamples * (endGain - startGain). This\r
+                                    ensures a continuous ramp when supplying the same value in\r
+                                    endGain and startGain in subsequent blocks. The gain is linearly\r
                                     interpolated between the first and last samples.\r
     */\r
     void addFromWithRamp (int destChannel,\r
@@ -1043,7 +1055,11 @@ public:
         @param numSamples           the number of samples to process\r
         @param startGain            the gain to apply to the first sample (this is multiplied with\r
                                     the source samples before they are copied to this buffer)\r
-        @param endGain              the gain to apply to the final sample. The gain is linearly\r
+        @param endGain              The gain that would apply to the sample after the final sample.\r
+                                    The gain that applies to the final sample is\r
+                                    (numSamples - 1) / numSamples * (endGain - startGain). This\r
+                                    ensures a continuous ramp when supplying the same value in\r
+                                    endGain and startGain in subsequent blocks. The gain is linearly\r
                                     interpolated between the first and last samples.\r
 \r
         @see addFrom\r
@@ -1177,7 +1193,7 @@ private:
         jassert (size >= 0);\r
 \r
         auto channelListSize = (size_t) (numChannels + 1) * sizeof (Type*);\r
-        auto requiredSampleAlignment = std::alignment_of<Type>::value;\r
+        auto requiredSampleAlignment = std::alignment_of_v<Type>;\r
         size_t alignmentOverflow = channelListSize % requiredSampleAlignment;\r
 \r
         if (alignmentOverflow != 0)\r
index 1e5af0e638e200290b391dbc5ab02382766bd15d..2a576dc989b55fb45f28b17a83255431a2bb4d37 100644 (file)
@@ -938,15 +938,13 @@ namespace
        #if JUCE_USE_VDSP_FRAMEWORK\r
         vDSP_vabs ((float*) src, 1, dest, 1, (vDSP_Length) num);\r
        #else\r
-        FloatVectorHelpers::signMask32 signMask;\r
+        [[maybe_unused]] FloatVectorHelpers::signMask32 signMask;\r
         signMask.i = 0x7fffffffUL;\r
         JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = std::abs (src[i]),\r
                                       Mode::bit_and (s, mask),\r
                                       JUCE_LOAD_SRC,\r
                                       JUCE_INCREMENT_SRC_DEST,\r
                                       const Mode::ParallelType mask = Mode::load1 (signMask.f);)\r
-\r
-        ignoreUnused (signMask);\r
        #endif\r
     }\r
 \r
@@ -956,7 +954,7 @@ namespace
        #if JUCE_USE_VDSP_FRAMEWORK\r
         vDSP_vabsD ((double*) src, 1, dest, 1, (vDSP_Length) num);\r
        #else\r
-        FloatVectorHelpers::signMask64 signMask;\r
+        [[maybe_unused]] FloatVectorHelpers::signMask64 signMask;\r
         signMask.i = 0x7fffffffffffffffULL;\r
 \r
         JUCE_PERFORM_VEC_OP_SRC_DEST (dest[i] = std::abs (src[i]),\r
@@ -964,8 +962,6 @@ namespace
                                       JUCE_LOAD_SRC,\r
                                       JUCE_INCREMENT_SRC_DEST,\r
                                       const Mode::ParallelType mask = Mode::load1 (signMask.d);)\r
-\r
-        ignoreUnused (signMask);\r
        #endif\r
     }\r
 \r
@@ -1430,34 +1426,44 @@ void JUCE_CALLTYPE FloatVectorOperations::convertFixedToFloat (float* dest, cons
 intptr_t JUCE_CALLTYPE FloatVectorOperations::getFpStatusRegister() noexcept\r
 {\r
     intptr_t fpsr = 0;\r
 #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS\r
+ #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS\r
     fpsr = static_cast<intptr_t> (_mm_getcsr());\r
-  #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON\r
-   #if defined(__arm64__) || defined(__aarch64__)\r
+ #elif (JUCE_64BIT && JUCE_ARM) || JUCE_USE_ARM_NEON\r
+  #if _MSC_VER\r
+    // _control87 returns static values for x86 bits that don't exist on arm\r
+    // to emulate x86 behaviour. We are only ever interested in de-normal bits\r
+    // so mask out only those.\r
+    fpsr = (intptr_t) (_control87 (0, 0) & _MCW_DN);\r
+  #else\r
+   #if JUCE_64BIT\r
     asm volatile("mrs %0, fpcr"\r
                  : "=r"(fpsr));\r
    #elif JUCE_USE_ARM_NEON\r
     asm volatile("vmrs %0, fpscr"\r
                  : "=r"(fpsr));\r
    #endif\r
-  #else\r
-   #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))\r
+  #endif\r
+ #else\r
+  #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))\r
     jassertfalse; // No support for getting the floating point status register for your platform\r
-   #endif\r
   #endif\r
+ #endif\r
 \r
     return fpsr;\r
 }\r
 \r
-void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) noexcept\r
+void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister ([[maybe_unused]] intptr_t fpsr) noexcept\r
 {\r
 #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS\r
+ #if JUCE_INTEL && JUCE_USE_SSE_INTRINSICS\r
     // the volatile keyword here is needed to workaround a bug in AppleClang 13.0\r
     // which aggressively optimises away the variable otherwise\r
     volatile auto fpsr_w = static_cast<uint32_t> (fpsr);\r
     _mm_setcsr (fpsr_w);\r
-  #elif defined(__arm64__) || defined(__aarch64__) || JUCE_USE_ARM_NEON\r
-   #if defined(__arm64__) || defined(__aarch64__)\r
+ #elif (JUCE_64BIT && JUCE_ARM) || JUCE_USE_ARM_NEON\r
+  #if _MSC_VER\r
+    _control87 ((unsigned int) fpsr, _MCW_DN);\r
+  #else\r
+   #if JUCE_64BIT\r
     asm volatile("msr fpcr, %0"\r
                  :\r
                  : "ri"(fpsr));\r
@@ -1466,17 +1472,17 @@ void JUCE_CALLTYPE FloatVectorOperations::setFpStatusRegister (intptr_t fpsr) no
                  :\r
                  : "ri"(fpsr));\r
    #endif\r
-  #else\r
-   #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))\r
+  #endif\r
+ #else\r
+  #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))\r
     jassertfalse; // No support for getting the floating point status register for your platform\r
-   #endif\r
-    ignoreUnused (fpsr);\r
   #endif\r
+ #endif\r
 }\r
 \r
-void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnable) noexcept\r
+void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode ([[maybe_unused]] bool shouldEnable) noexcept\r
 {\r
-  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
    #if JUCE_USE_SSE_INTRINSICS\r
     intptr_t mask = _MM_FLUSH_ZERO_MASK;\r
    #else /*JUCE_USE_ARM_NEON*/\r
@@ -1484,16 +1490,15 @@ void JUCE_CALLTYPE FloatVectorOperations::enableFlushToZeroMode (bool shouldEnab
    #endif\r
     setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldEnable ? mask : 0));\r
   #else\r
-   #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))\r
+   #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))\r
     jassertfalse; // No support for flush to zero mode on your platform\r
    #endif\r
-    ignoreUnused (shouldEnable);\r
   #endif\r
 }\r
 \r
-void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool shouldDisable) noexcept\r
+void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport ([[maybe_unused]] bool shouldDisable) noexcept\r
 {\r
-  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
    #if JUCE_USE_SSE_INTRINSICS\r
     intptr_t mask = 0x8040;\r
    #else /*JUCE_USE_ARM_NEON*/\r
@@ -1502,9 +1507,8 @@ void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool
 \r
     setFpStatusRegister ((getFpStatusRegister() & (~mask)) | (shouldDisable ? mask : 0));\r
   #else\r
-    ignoreUnused (shouldDisable);\r
 \r
-   #if ! (defined(JUCE_INTEL) || defined(JUCE_ARM))\r
+   #if ! (defined (JUCE_INTEL) || defined (JUCE_ARM))\r
     jassertfalse; // No support for disable denormals mode on your platform\r
    #endif\r
   #endif\r
@@ -1512,7 +1516,7 @@ void JUCE_CALLTYPE FloatVectorOperations::disableDenormalisedNumberSupport (bool
 \r
 bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept\r
 {\r
-  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
    #if JUCE_USE_SSE_INTRINSICS\r
     intptr_t mask = 0x8040;\r
    #else /*JUCE_USE_ARM_NEON*/\r
@@ -1527,7 +1531,7 @@ bool JUCE_CALLTYPE FloatVectorOperations::areDenormalsDisabled() noexcept
 \r
 ScopedNoDenormals::ScopedNoDenormals() noexcept\r
 {\r
-  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
    #if JUCE_USE_SSE_INTRINSICS\r
     intptr_t mask = 0x8040;\r
    #else /*JUCE_USE_ARM_NEON*/\r
@@ -1541,7 +1545,7 @@ ScopedNoDenormals::ScopedNoDenormals() noexcept
 \r
 ScopedNoDenormals::~ScopedNoDenormals() noexcept\r
 {\r
-   #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined(__arm64__) || defined(__aarch64__))\r
+   #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
     FloatVectorOperations::setFpStatusRegister (fpsr);\r
    #endif\r
 }\r
index 3f0f0366e7435bd44f90cef2aa987583979cccea..9c6ed4990936a6bac48f239a4d49cac8272f1951 100644 (file)
@@ -142,65 +142,26 @@ struct FloatVectorOperationsBase
 namespace detail\r
 {\r
 \r
-template <typename...>\r
-struct NameForwarder;\r
-\r
-template <typename Head>\r
-struct NameForwarder<Head> : Head {};\r
-\r
-template <typename Head, typename... Tail>\r
-struct NameForwarder<Head, Tail...> : Head, NameForwarder<Tail...>\r
+template <typename... Bases>\r
+struct NameForwarder : public Bases...\r
 {\r
-    using Head::clear;\r
-    using NameForwarder<Tail...>::clear;\r
-\r
-    using Head::fill;\r
-    using NameForwarder<Tail...>::fill;\r
-\r
-    using Head::copy;\r
-    using NameForwarder<Tail...>::copy;\r
-\r
-    using Head::copyWithMultiply;\r
-    using NameForwarder<Tail...>::copyWithMultiply;\r
-\r
-    using Head::add;\r
-    using NameForwarder<Tail...>::add;\r
-\r
-    using Head::subtract;\r
-    using NameForwarder<Tail...>::subtract;\r
-\r
-    using Head::addWithMultiply;\r
-    using NameForwarder<Tail...>::addWithMultiply;\r
-\r
-    using Head::subtractWithMultiply;\r
-    using NameForwarder<Tail...>::subtractWithMultiply;\r
-\r
-    using Head::multiply;\r
-    using NameForwarder<Tail...>::multiply;\r
-\r
-    using Head::negate;\r
-    using NameForwarder<Tail...>::negate;\r
-\r
-    using Head::abs;\r
-    using NameForwarder<Tail...>::abs;\r
-\r
-    using Head::min;\r
-    using NameForwarder<Tail...>::min;\r
-\r
-    using Head::max;\r
-    using NameForwarder<Tail...>::max;\r
-\r
-    using Head::clip;\r
-    using NameForwarder<Tail...>::clip;\r
-\r
-    using Head::findMinAndMax;\r
-    using NameForwarder<Tail...>::findMinAndMax;\r
-\r
-    using Head::findMinimum;\r
-    using NameForwarder<Tail...>::findMinimum;\r
-\r
-    using Head::findMaximum;\r
-    using NameForwarder<Tail...>::findMaximum;\r
+    using Bases::clear...,\r
+          Bases::fill...,\r
+          Bases::copy...,\r
+          Bases::copyWithMultiply...,\r
+          Bases::add...,\r
+          Bases::subtract...,\r
+          Bases::addWithMultiply...,\r
+          Bases::subtractWithMultiply...,\r
+          Bases::multiply...,\r
+          Bases::negate...,\r
+          Bases::abs...,\r
+          Bases::min...,\r
+          Bases::max...,\r
+          Bases::clip...,\r
+          Bases::findMinAndMax...,\r
+          Bases::findMinimum...,\r
+          Bases::findMaximum...;\r
 };\r
 \r
 } // namespace detail\r
@@ -261,7 +222,7 @@ public:
     ~ScopedNoDenormals() noexcept;\r
 \r
 private:\r
-  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || defined (__arm64__) || defined (__aarch64__))\r
+  #if JUCE_USE_SSE_INTRINSICS || (JUCE_USE_ARM_NEON || (JUCE_64BIT && JUCE_ARM))\r
     intptr_t fpsr;\r
   #endif\r
 };\r
index 10f3a9bbcaf128100ad08b00bd3d6349b077103d..570974762e595dd62b2a5d19169b830202690af6 100644 (file)
 #include "sources/juce_ResamplingAudioSource.cpp"\r
 #include "sources/juce_ReverbAudioSource.cpp"\r
 #include "sources/juce_ToneGeneratorAudioSource.cpp"\r
+#include "sources/juce_PositionableAudioSource.cpp"\r
 #include "synthesisers/juce_Synthesiser.cpp"\r
+#include "audio_play_head/juce_AudioPlayHead.cpp"\r
 \r
 #include "midi/ump/juce_UMP.h"\r
 #include "midi/ump/juce_UMPUtils.cpp"\r
 #include "midi/ump/juce_UMPView.cpp"\r
 #include "midi/ump/juce_UMPSysEx7.cpp"\r
 #include "midi/ump/juce_UMPMidi1ToMidi2DefaultTranslator.cpp"\r
+#include "midi/ump/juce_UMPIterator.cpp"\r
 \r
 #if JUCE_UNIT_TESTS\r
  #include "utilities/juce_ADSR_test.cpp"\r
index 46d5883abc5216cd6e47d9b6cc9ae6810f37c21b..85c0c437ed65f1a78a0b88136318206d5e0d0479 100644 (file)
 \r
   ID:                 juce_audio_basics\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE audio and MIDI data classes\r
   description:        Classes for audio buffer manipulation, midi message handling, synthesis, etc.\r
   website:            http://www.juce.com/juce\r
   license:            ISC\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_core\r
   OSXFrameworks:      Accelerate\r
@@ -83,7 +83,9 @@
 \r
 //==============================================================================\r
 #include "buffers/juce_AudioDataConverters.h"\r
+JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4661)\r
 #include "buffers/juce_FloatVectorOperations.h"\r
+JUCE_END_IGNORE_WARNINGS_MSVC\r
 #include "buffers/juce_AudioSampleBuffer.h"\r
 #include "buffers/juce_AudioChannelSet.h"\r
 #include "buffers/juce_AudioProcessLoadMeasurer.h"\r
diff --git a/modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp b/modules/juce_audio_basics/midi/ump/juce_UMPIterator.cpp
new file mode 100644 (file)
index 0000000..0ba7ce0
--- /dev/null
@@ -0,0 +1,37 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   The code included in this file is provided under the terms of the ISC license\r
+   http://www.isc.org/downloads/software-support-policy/isc-license. Permission\r
+   To use, copy, modify, and/or distribute this software for any purpose with or\r
+   without fee is hereby granted provided that the above copyright notice and\r
+   this permission notice appear in all copies.\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+namespace universal_midi_packets\r
+{\r
+\r
+Iterator::Iterator (const uint32_t* ptr, [[maybe_unused]] size_t bytes) noexcept\r
+    : view (ptr)\r
+   #if JUCE_DEBUG\r
+    , bytesRemaining (bytes)\r
+   #endif\r
+{\r
+}\r
+\r
+} // namespace universal_midi_packets\r
+} // namespace juce\r
index b4dcea9a3446470739bbde2153f93355a0a7bf93..eba6202956e2e4cc80db813a8a56557d0c7fc8f3 100644 (file)
@@ -43,14 +43,7 @@ public:
     Iterator() noexcept = default;\r
 \r
     /** Creates an iterator pointing at `ptr`. */\r
-    explicit Iterator (const uint32_t* ptr, size_t bytes) noexcept\r
-        : view (ptr)\r
-       #if JUCE_DEBUG\r
-        , bytesRemaining (bytes)\r
-       #endif\r
-    {\r
-        ignoreUnused (bytes);\r
-    }\r
+    explicit Iterator (const uint32_t* ptr, size_t bytes) noexcept;\r
 \r
     using difference_type    = std::iterator_traits<const uint32_t*>::difference_type;\r
     using value_type         = View;\r
@@ -124,7 +117,7 @@ private:
    #endif\r
 };\r
 \r
-}\r
-}\r
+} // namespace universal_midi_packets\r
+} // namespace juce\r
 \r
 #endif\r
index 0186bef6a97e9d2b050e20c41ed352f7f74f5794..e9f70d6def2110dfacf6cfbdbfac5607e52b8744 100644 (file)
@@ -33,7 +33,7 @@ namespace universal_midi_packets
     The packet must be well-formed for member functions to work correctly.\r
 \r
     Specifically, the constructor argument must be the beginning of a region of\r
-    uint32_t that contains at least `getNumWordsForMessageType(*ddata)` items,\r
+    uint32_t that contains at least `getNumWordsForMessageType(*data)` items,\r
     where `data` is the constructor argument.\r
 \r
     NOTE: Instances of this class do not own the memory that they point to!\r
index 0706b13baec27aa5cb2b2e3e45cbc799d6b16f39..fd52554bbe869bad90f94fce10d19d3eb9505ed8 100644 (file)
@@ -992,7 +992,7 @@ private:
 \r
    #if JUCE_WINDOWS && ! JUCE_MINGW\r
     #define JUCE_CHECKED_ITERATOR(msg, size) \\r
-        stdext::checked_array_iterator<typename std::remove_reference<decltype (msg)>::type> ((msg), (size_t) (size))\r
+        stdext::checked_array_iterator<std::remove_reference_t<decltype (msg)>> ((msg), (size_t) (size))\r
    #else\r
     #define JUCE_CHECKED_ITERATOR(msg, size) (msg)\r
    #endif\r
index c0e855d3c834035b1bae00d9afa38c46648b99d9..ef811510a15547a3cccf715b6da87fb2ea28cdfb 100644 (file)
@@ -38,35 +38,35 @@ class Packet
 public:\r
     Packet() = default;\r
 \r
-    template <size_t w = numWords, typename std::enable_if<w == 1, int>::type = 0>\r
+    template <size_t w = numWords, std::enable_if_t<w == 1, int> = 0>\r
     Packet (uint32_t a)\r
         : contents { { a } }\r
     {\r
         jassert (Utils::getNumWordsForMessageType (a) == 1);\r
     }\r
 \r
-    template <size_t w = numWords, typename std::enable_if<w == 2, int>::type = 0>\r
+    template <size_t w = numWords, std::enable_if_t<w == 2, int> = 0>\r
     Packet (uint32_t a, uint32_t b)\r
         : contents { { a, b } }\r
     {\r
         jassert (Utils::getNumWordsForMessageType (a) == 2);\r
     }\r
 \r
-    template <size_t w = numWords, typename std::enable_if<w == 3, int>::type = 0>\r
+    template <size_t w = numWords, std::enable_if_t<w == 3, int> = 0>\r
     Packet (uint32_t a, uint32_t b, uint32_t c)\r
         : contents { { a, b, c } }\r
     {\r
         jassert (Utils::getNumWordsForMessageType (a) == 3);\r
     }\r
 \r
-    template <size_t w = numWords, typename std::enable_if<w == 4, int>::type = 0>\r
+    template <size_t w = numWords, std::enable_if_t<w == 4, int> = 0>\r
     Packet (uint32_t a, uint32_t b, uint32_t c, uint32_t d)\r
         : contents { { a, b, c, d } }\r
     {\r
         jassert (Utils::getNumWordsForMessageType (a) == 4);\r
     }\r
 \r
-    template <size_t w, typename std::enable_if<w == numWords, int>::type = 0>\r
+    template <size_t w, std::enable_if_t<w == numWords, int> = 0>\r
     explicit Packet (const std::array<uint32_t, w>& fullPacket)\r
         : contents (fullPacket)\r
     {\r
index 576b8b38164cf337d8db2ce4ddcae23e8473b513..87f3df39f7241c23a052a58de8f182b1f724629a 100644 (file)
@@ -853,6 +853,14 @@ void MPEInstrument::releaseAllNotes()
     notes.clear();\r
 }\r
 \r
+//==============================================================================\r
+void MPEInstrument::Listener::noteAdded ([[maybe_unused]] MPENote newNote)                 {}\r
+void MPEInstrument::Listener::notePressureChanged  ([[maybe_unused]] MPENote changedNote)  {}\r
+void MPEInstrument::Listener::notePitchbendChanged ([[maybe_unused]] MPENote changedNote)  {}\r
+void MPEInstrument::Listener::noteTimbreChanged    ([[maybe_unused]] MPENote changedNote)  {}\r
+void MPEInstrument::Listener::noteKeyStateChanged  ([[maybe_unused]] MPENote changedNote)  {}\r
+void MPEInstrument::Listener::noteReleased ([[maybe_unused]] MPENote finishedNote)         {}\r
+void MPEInstrument::Listener::zoneLayoutChanged()                                          {}\r
 \r
 //==============================================================================\r
 //==============================================================================\r
index 291957413338b55b514f5a9c5909f20ef69a2579..e7993c1d12e0020ced4fe1b301aa27d49db728b2 100644 (file)
@@ -265,12 +265,12 @@ public:
         /** Implement this callback to be informed whenever a new expressive MIDI\r
             note is triggered.\r
         */\r
-        virtual void noteAdded (MPENote newNote)                 { ignoreUnused (newNote); }\r
+        virtual void noteAdded (MPENote newNote);\r
 \r
         /** Implement this callback to be informed whenever a currently playing\r
             MPE note's pressure value changes.\r
         */\r
-        virtual void notePressureChanged (MPENote changedNote)   { ignoreUnused (changedNote); }\r
+        virtual void notePressureChanged (MPENote changedNote);\r
 \r
         /** Implement this callback to be informed whenever a currently playing\r
             MPE note's pitchbend value changes.\r
@@ -279,12 +279,12 @@ public:
             master channel pitchbend event, or if both occur simultaneously.\r
             Call MPENote::getFrequencyInHertz to get the effective note frequency.\r
         */\r
-        virtual void notePitchbendChanged (MPENote changedNote)  { ignoreUnused (changedNote); }\r
+        virtual void notePitchbendChanged (MPENote changedNote);\r
 \r
         /** Implement this callback to be informed whenever a currently playing\r
             MPE note's timbre value changes.\r
         */\r
-        virtual void noteTimbreChanged (MPENote changedNote)     { ignoreUnused (changedNote); }\r
+        virtual void noteTimbreChanged (MPENote changedNote);\r
 \r
         /** Implement this callback to be informed whether a currently playing\r
             MPE note's key state (whether the key is down and/or the note is\r
@@ -293,19 +293,19 @@ public:
             Note: If the key state changes to MPENote::off, noteReleased is\r
             called instead.\r
         */\r
-        virtual void noteKeyStateChanged (MPENote changedNote)   { ignoreUnused (changedNote); }\r
+        virtual void noteKeyStateChanged (MPENote changedNote);\r
 \r
         /** Implement this callback to be informed whenever an MPE note\r
             is released (either by a note-off message, or by a sustain/sostenuto\r
             pedal release for a note that already received a note-off),\r
             and should therefore stop playing.\r
         */\r
-        virtual void noteReleased (MPENote finishedNote)         { ignoreUnused (finishedNote); }\r
+        virtual void noteReleased (MPENote finishedNote);\r
 \r
         /** Implement this callback to be informed whenever the MPE zone layout\r
             or legacy mode settings of this instrument have been changed.\r
         */\r
-        virtual void zoneLayoutChanged()                         {}\r
+        virtual void zoneLayoutChanged();\r
     };\r
 \r
     //==============================================================================\r
index fde51b29330eb4fded8d60610e141975d0a74372..f89d3ae6a3b6a6c612ebb4bcaf00756cbb0fdff7 100644 (file)
@@ -184,15 +184,19 @@ MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceF
     MPESynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase\r
     MPESynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase\r
 \r
+    // All major OSes use double-locking so this will be lock- and wait-free as long as stealLock is not\r
+    // contended. This is always the case if you do not call findVoiceToSteal on multiple threads at\r
+    // the same time.\r
+    const ScopedLock sl (stealLock);\r
+\r
     // this is a list of voices we can steal, sorted by how long they've been running\r
-    Array<MPESynthesiserVoice*> usableVoices;\r
-    usableVoices.ensureStorageAllocated (voices.size());\r
+    usableVoicesToStealArray.clear();\r
 \r
     for (auto* voice : voices)\r
     {\r
         jassert (voice->isActive()); // We wouldn't be here otherwise\r
 \r
-        usableVoices.add (voice);\r
+        usableVoicesToStealArray.add (voice);\r
 \r
         // NB: Using a functor rather than a lambda here due to scare-stories about\r
         // compilers generating code containing heap allocations..\r
@@ -201,7 +205,7 @@ MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceF
             bool operator() (const MPESynthesiserVoice* a, const MPESynthesiserVoice* b) const noexcept { return a->noteOnTime < b->noteOnTime; }\r
         };\r
 \r
-        std::sort (usableVoices.begin(), usableVoices.end(), Sorter());\r
+        std::sort (usableVoicesToStealArray.begin(), usableVoicesToStealArray.end(), Sorter());\r
 \r
         if (! voice->isPlayingButReleased()) // Don't protect released notes\r
         {\r
@@ -222,24 +226,24 @@ MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceF
     // If we want to re-use the voice to trigger a new note,\r
     // then The oldest note that's playing the same note number is ideal.\r
     if (noteToStealVoiceFor.isValid())\r
-        for (auto* voice : usableVoices)\r
+        for (auto* voice : usableVoicesToStealArray)\r
             if (voice->getCurrentlyPlayingNote().initialNote == noteToStealVoiceFor.initialNote)\r
                 return voice;\r
 \r
     // Oldest voice that has been released (no finger on it and not held by sustain pedal)\r
-    for (auto* voice : usableVoices)\r
+    for (auto* voice : usableVoicesToStealArray)\r
         if (voice != low && voice != top && voice->isPlayingButReleased())\r
             return voice;\r
 \r
     // Oldest voice that doesn't have a finger on it:\r
-    for (auto* voice : usableVoices)\r
+    for (auto* voice : usableVoicesToStealArray)\r
         if (voice != low && voice != top\r
              && voice->getCurrentlyPlayingNote().keyState != MPENote::keyDown\r
              && voice->getCurrentlyPlayingNote().keyState != MPENote::keyDownAndSustained)\r
             return voice;\r
 \r
     // Oldest voice that isn't protected\r
-    for (auto* voice : usableVoices)\r
+    for (auto* voice : usableVoicesToStealArray)\r
         if (voice != low && voice != top)\r
             return voice;\r
 \r
@@ -256,9 +260,16 @@ MPESynthesiserVoice* MPESynthesiser::findVoiceToSteal (MPENote noteToStealVoiceF
 //==============================================================================\r
 void MPESynthesiser::addVoice (MPESynthesiserVoice* const newVoice)\r
 {\r
-    const ScopedLock sl (voicesLock);\r
-    newVoice->setCurrentSampleRate (getSampleRate());\r
-    voices.add (newVoice);\r
+    {\r
+        const ScopedLock sl (voicesLock);\r
+        newVoice->setCurrentSampleRate (getSampleRate());\r
+        voices.add (newVoice);\r
+    }\r
+\r
+    {\r
+        const ScopedLock sl (stealLock);\r
+        usableVoicesToStealArray.ensureStorageAllocated (voices.size() + 1);\r
+    }\r
 }\r
 \r
 void MPESynthesiser::clearVoices()\r
index 9a443c5f94c57f40b3a3c3c2d211cd94f36bfda7..bc4c1b40838aa70387aa1e970715907c1570a744 100644 (file)
@@ -304,6 +304,8 @@ private:
     //==============================================================================\r
     std::atomic<bool> shouldStealVoices { false };\r
     uint32 lastNoteOnCounter = 0;\r
+    mutable CriticalSection stealLock;\r
+    mutable Array<MPESynthesiserVoice*> usableVoicesToStealArray;\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MPESynthesiser)\r
 };\r
diff --git a/modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp b/modules/juce_audio_basics/sources/juce_PositionableAudioSource.cpp
new file mode 100644 (file)
index 0000000..d7fbe37
--- /dev/null
@@ -0,0 +1,28 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   The code included in this file is provided under the terms of the ISC license\r
+   http://www.isc.org/downloads/software-support-policy/isc-license. Permission\r
+   To use, copy, modify, and/or distribute this software for any purpose with or\r
+   without fee is hereby granted provided that the above copyright notice and\r
+   this permission notice appear in all copies.\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+void PositionableAudioSource::setLooping ([[maybe_unused]] bool shouldLoop) {}\r
+\r
+} // namespace juce\r
index 1898bbbcfdd8f06c2610b0086e4ef0aeb021de10..6fb6691eaf955b78d2fb5482ed1630c48ba50a88 100644 (file)
@@ -70,7 +70,7 @@ public:
     virtual bool isLooping() const = 0;\r
 \r
     /** Tells the source whether you'd like it to play in a loop. */\r
-    virtual void setLooping (bool shouldLoop)       { ignoreUnused (shouldLoop); }\r
+    virtual void setLooping (bool shouldLoop);\r
 };\r
 \r
 } // namespace juce\r
index c407911f30746d1e55fd2e31b8feb6c1afe70694..f9aaff23f0d23e2273482b6514abd453d04b4b1f 100644 (file)
@@ -98,9 +98,20 @@ void Synthesiser::clearVoices()
 \r
 SynthesiserVoice* Synthesiser::addVoice (SynthesiserVoice* const newVoice)\r
 {\r
-    const ScopedLock sl (lock);\r
-    newVoice->setCurrentPlaybackSampleRate (sampleRate);\r
-    return voices.add (newVoice);\r
+    SynthesiserVoice* voice;\r
+\r
+    {\r
+        const ScopedLock sl (lock);\r
+        newVoice->setCurrentPlaybackSampleRate (sampleRate);\r
+        voice = voices.add (newVoice);\r
+    }\r
+\r
+    {\r
+        const ScopedLock sl (stealLock);\r
+        usableVoicesToStealArray.ensureStorageAllocated (voices.size() + 1);\r
+    }\r
+\r
+    return voice;\r
 }\r
 \r
 void Synthesiser::removeVoice (const int index)\r
@@ -471,15 +482,14 @@ void Synthesiser::handleSostenutoPedal (int midiChannel, bool isDown)
     }\r
 }\r
 \r
-void Synthesiser::handleSoftPedal (int midiChannel, bool /*isDown*/)\r
+void Synthesiser::handleSoftPedal ([[maybe_unused]] int midiChannel, bool /*isDown*/)\r
 {\r
-    ignoreUnused (midiChannel);\r
     jassert (midiChannel > 0 && midiChannel <= 16);\r
 }\r
 \r
-void Synthesiser::handleProgramChange (int midiChannel, int programNumber)\r
+void Synthesiser::handleProgramChange ([[maybe_unused]] int midiChannel,\r
+                                       [[maybe_unused]] int programNumber)\r
 {\r
-    ignoreUnused (midiChannel, programNumber);\r
     jassert (midiChannel > 0 && midiChannel <= 16);\r
 }\r
 \r
@@ -514,9 +524,13 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
     SynthesiserVoice* low = nullptr; // Lowest sounding note, might be sustained, but NOT in release phase\r
     SynthesiserVoice* top = nullptr; // Highest sounding note, might be sustained, but NOT in release phase\r
 \r
+    // All major OSes use double-locking so this will be lock- and wait-free as long as the lock is not\r
+    // contended. This is always the case if you do not call findVoiceToSteal on multiple threads at\r
+    // the same time.\r
+    const ScopedLock sl (stealLock);\r
+\r
     // this is a list of voices we can steal, sorted by how long they've been running\r
-    Array<SynthesiserVoice*> usableVoices;\r
-    usableVoices.ensureStorageAllocated (voices.size());\r
+    usableVoicesToStealArray.clear();\r
 \r
     for (auto* voice : voices)\r
     {\r
@@ -524,7 +538,7 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
         {\r
             jassert (voice->isVoiceActive()); // We wouldn't be here otherwise\r
 \r
-            usableVoices.add (voice);\r
+            usableVoicesToStealArray.add (voice);\r
 \r
             // NB: Using a functor rather than a lambda here due to scare-stories about\r
             // compilers generating code containing heap allocations..\r
@@ -533,7 +547,7 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
                 bool operator() (const SynthesiserVoice* a, const SynthesiserVoice* b) const noexcept { return a->wasStartedBefore (*b); }\r
             };\r
 \r
-            std::sort (usableVoices.begin(), usableVoices.end(), Sorter());\r
+            std::sort (usableVoicesToStealArray.begin(), usableVoicesToStealArray.end(), Sorter());\r
 \r
             if (! voice->isPlayingButReleased()) // Don't protect released notes\r
             {\r
@@ -553,22 +567,22 @@ SynthesiserVoice* Synthesiser::findVoiceToSteal (SynthesiserSound* soundToPlay,
         top = nullptr;\r
 \r
     // The oldest note that's playing with the target pitch is ideal..\r
-    for (auto* voice : usableVoices)\r
+    for (auto* voice : usableVoicesToStealArray)\r
         if (voice->getCurrentlyPlayingNote() == midiNoteNumber)\r
             return voice;\r
 \r
     // Oldest voice that has been released (no finger on it and not held by sustain pedal)\r
-    for (auto* voice : usableVoices)\r
+    for (auto* voice : usableVoicesToStealArray)\r
         if (voice != low && voice != top && voice->isPlayingButReleased())\r
             return voice;\r
 \r
     // Oldest voice that doesn't have a finger on it:\r
-    for (auto* voice : usableVoices)\r
+    for (auto* voice : usableVoicesToStealArray)\r
         if (voice != low && voice != top && ! voice->isKeyDown())\r
             return voice;\r
 \r
     // Oldest voice that isn't protected\r
-    for (auto* voice : usableVoices)\r
+    for (auto* voice : usableVoicesToStealArray)\r
         if (voice != low && voice != top)\r
             return voice;\r
 \r
index b9db266cc32b5e1c730d65be69aba1cea56201cd..5010667cb214425fba1e19dc954c9cafd70dbe6e 100644 (file)
@@ -627,6 +627,8 @@ private:
     bool subBlockSubdivisionIsStrict = false;\r
     bool shouldStealNotes = true;\r
     BigInteger sustainPedalsDown;\r
+    mutable CriticalSection stealLock;\r
+    mutable Array<SynthesiserVoice*> usableVoicesToStealArray;\r
 \r
     template <typename floatType>\r
     void processNextBlock (AudioBuffer<floatType>&, const MidiBuffer&, int startSample, int numSamples);\r
index 084927d24da7da48ee2dc614e3feb02f06c350ca..5427f02a44eea5165b03ae04f42ce22baea2d257 100644 (file)
@@ -39,6 +39,16 @@ namespace juce
 template <class InterpolatorTraits, int memorySize>\r
 class JUCE_API  GenericInterpolator\r
 {\r
+    static auto processReplacingCallback()\r
+    {\r
+        return [] (auto, auto newValue) { return newValue; };\r
+    }\r
+\r
+    static auto processAddingCallback (float gain)\r
+    {\r
+        return [gain] (auto oldValue, auto newValue) { return oldValue + gain * newValue; };\r
+    }\r
+\r
 public:\r
     GenericInterpolator() noexcept                        { reset(); }\r
 \r
@@ -81,7 +91,11 @@ public:
                  float* outputSamples,\r
                  int numOutputSamplesToProduce) noexcept\r
     {\r
-        return interpolate (speedRatio, inputSamples, outputSamples, numOutputSamplesToProduce);\r
+        return interpolateImpl (speedRatio,\r
+                                inputSamples,\r
+                                outputSamples,\r
+                                numOutputSamplesToProduce,\r
+                                processReplacingCallback());\r
     }\r
 \r
     /** Resamples a stream of samples.\r
@@ -106,8 +120,13 @@ public:
                  int numInputSamplesAvailable,\r
                  int wrapAround) noexcept\r
     {\r
-        return interpolate (speedRatio, inputSamples, outputSamples,\r
-                            numOutputSamplesToProduce, numInputSamplesAvailable, wrapAround);\r
+        return interpolateImpl (speedRatio,\r
+                                inputSamples,\r
+                                outputSamples,\r
+                                numOutputSamplesToProduce,\r
+                                numInputSamplesAvailable,\r
+                                wrapAround,\r
+                                processReplacingCallback());\r
     }\r
 \r
     /** Resamples a stream of samples, adding the results to the output data\r
@@ -131,7 +150,11 @@ public:
                        int numOutputSamplesToProduce,\r
                        float gain) noexcept\r
     {\r
-        return interpolateAdding (speedRatio, inputSamples, outputSamples, numOutputSamplesToProduce, gain);\r
+        return interpolateImpl (speedRatio,\r
+                                inputSamples,\r
+                                outputSamples,\r
+                                numOutputSamplesToProduce,\r
+                                processAddingCallback (gain));\r
     }\r
 \r
     /** Resamples a stream of samples, adding the results to the output data\r
@@ -162,8 +185,13 @@ public:
                        int wrapAround,\r
                        float gain) noexcept\r
     {\r
-        return interpolateAdding (speedRatio, inputSamples, outputSamples,\r
-                                  numOutputSamplesToProduce, numInputSamplesAvailable, wrapAround, gain);\r
+        return interpolateImpl (speedRatio,\r
+                                inputSamples,\r
+                                outputSamples,\r
+                                numOutputSamplesToProduce,\r
+                                numInputSamplesAvailable,\r
+                                wrapAround,\r
+                                processAddingCallback (gain));\r
     }\r
 \r
 private:\r
@@ -255,113 +283,48 @@ private:
     }\r
 \r
     //==============================================================================\r
-    int interpolate (double speedRatio,\r
-                     const float* input,\r
-                     float* output,\r
-                     int numOutputSamplesToProduce) noexcept\r
-    {\r
-        auto pos = subSamplePos;\r
-        int numUsed = 0;\r
-\r
-        while (numOutputSamplesToProduce > 0)\r
-        {\r
-            while (pos >= 1.0)\r
-            {\r
-                pushInterpolationSample (input[numUsed++]);\r
-                pos -= 1.0;\r
-            }\r
-\r
-            *output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);\r
-            pos += speedRatio;\r
-            --numOutputSamplesToProduce;\r
-        }\r
-\r
-        subSamplePos = pos;\r
-        return numUsed;\r
-    }\r
-\r
-    int interpolate (double speedRatio,\r
-                     const float* input, float* output,\r
-                     int numOutputSamplesToProduce,\r
-                     int numInputSamplesAvailable,\r
-                     int wrap) noexcept\r
+    template <typename Process>\r
+    int interpolateImpl (double speedRatio,\r
+                         const float* input,\r
+                         float* output,\r
+                         int numOutputSamplesToProduce,\r
+                         int numInputSamplesAvailable,\r
+                         int wrap,\r
+                         Process process)\r
     {\r
         auto originalIn = input;\r
-        auto pos = subSamplePos;\r
         bool exceeded = false;\r
 \r
-        if (speedRatio < 1.0)\r
+        const auto pushSample = [&]\r
         {\r
-            for (int i = numOutputSamplesToProduce; --i >= 0;)\r
+            if (exceeded)\r
             {\r
-                if (pos >= 1.0)\r
-                {\r
-                    if (exceeded)\r
-                    {\r
-                        pushInterpolationSample (0.0f);\r
-                    }\r
-                    else\r
-                    {\r
-                        pushInterpolationSample (*input++);\r
-\r
-                        if (--numInputSamplesAvailable <= 0)\r
-                        {\r
-                            if (wrap > 0)\r
-                            {\r
-                                input -= wrap;\r
-                                numInputSamplesAvailable += wrap;\r
-                            }\r
-                            else\r
-                            {\r
-                                exceeded = true;\r
-                            }\r
-                        }\r
-                    }\r
-\r
-                    pos -= 1.0;\r
-                }\r
-\r
-                *output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);\r
-                pos += speedRatio;\r
+                pushInterpolationSample (0.0);\r
             }\r
-        }\r
-        else\r
-        {\r
-            for (int i = numOutputSamplesToProduce; --i >= 0;)\r
+            else\r
             {\r
-                while (pos < speedRatio)\r
+                pushInterpolationSample (*input++);\r
+\r
+                if (--numInputSamplesAvailable <= 0)\r
                 {\r
-                    if (exceeded)\r
+                    if (wrap > 0)\r
                     {\r
-                        pushInterpolationSample (0);\r
+                        input -= wrap;\r
+                        numInputSamplesAvailable += wrap;\r
                     }\r
                     else\r
                     {\r
-                        pushInterpolationSample (*input++);\r
-\r
-                        if (--numInputSamplesAvailable <= 0)\r
-                        {\r
-                            if (wrap > 0)\r
-                            {\r
-                                input -= wrap;\r
-                                numInputSamplesAvailable += wrap;\r
-                            }\r
-                            else\r
-                            {\r
-                                exceeded = true;\r
-                            }\r
-                        }\r
+                        exceeded = true;\r
                     }\r
-\r
-                    pos += 1.0;\r
                 }\r
-\r
-                pos -= speedRatio;\r
-                *output++ = InterpolatorTraits::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos), indexBuffer);\r
             }\r
-        }\r
+        };\r
 \r
-        subSamplePos = pos;\r
+        interpolateImpl (speedRatio,\r
+                         output,\r
+                         numOutputSamplesToProduce,\r
+                         process,\r
+                         pushSample);\r
 \r
         if (wrap == 0)\r
             return (int) (input - originalIn);\r
@@ -369,121 +332,47 @@ private:
         return ((int) (input - originalIn) + wrap) % wrap;\r
     }\r
 \r
-    int interpolateAdding (double speedRatio,\r
-                           const float* input,\r
-                           float* output,\r
-                           int numOutputSamplesToProduce,\r
-                           int numInputSamplesAvailable,\r
-                           int wrap,\r
-                           float gain) noexcept\r
+    template <typename Process>\r
+    int interpolateImpl (double speedRatio,\r
+                         const float* input,\r
+                         float* output,\r
+                         int numOutputSamplesToProduce,\r
+                         Process process)\r
     {\r
-        auto originalIn = input;\r
-        auto pos = subSamplePos;\r
-        bool exceeded = false;\r
-\r
-        if (speedRatio < 1.0)\r
-        {\r
-            for (int i = numOutputSamplesToProduce; --i >= 0;)\r
-            {\r
-                if (pos >= 1.0)\r
-                {\r
-                    if (exceeded)\r
-                    {\r
-                        pushInterpolationSample (0.0);\r
-                    }\r
-                    else\r
-                    {\r
-                        pushInterpolationSample (*input++);\r
-\r
-                        if (--numInputSamplesAvailable <= 0)\r
-                        {\r
-                            if (wrap > 0)\r
-                            {\r
-                                input -= wrap;\r
-                                numInputSamplesAvailable += wrap;\r
-                            }\r
-                            else\r
-                            {\r
-                                numInputSamplesAvailable = true;\r
-                            }\r
-                        }\r
-                    }\r
-\r
-                    pos -= 1.0;\r
-                }\r
-\r
-                *output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);\r
-                pos += speedRatio;\r
-            }\r
-        }\r
-        else\r
-        {\r
-            for (int i = numOutputSamplesToProduce; --i >= 0;)\r
-            {\r
-                while (pos < speedRatio)\r
-                {\r
-                    if (exceeded)\r
-                    {\r
-                        pushInterpolationSample (0.0);\r
-                    }\r
-                    else\r
-                    {\r
-                        pushInterpolationSample (*input++);\r
-\r
-                        if (--numInputSamplesAvailable <= 0)\r
-                        {\r
-                            if (wrap > 0)\r
-                            {\r
-                                input -= wrap;\r
-                                numInputSamplesAvailable += wrap;\r
-                            }\r
-                            else\r
-                            {\r
-                                exceeded = true;\r
-                            }\r
-                        }\r
-                    }\r
-\r
-                    pos += 1.0;\r
-                }\r
-\r
-                pos -= speedRatio;\r
-                *output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, jmax (0.0f, 1.0f - (float) pos), indexBuffer);\r
-            }\r
-        }\r
-\r
-        subSamplePos = pos;\r
+        int numUsed = 0;\r
 \r
-        if (wrap == 0)\r
-            return (int) (input - originalIn);\r
+        interpolateImpl (speedRatio,\r
+                         output,\r
+                         numOutputSamplesToProduce,\r
+                         process,\r
+                         [this, input, &numUsed] { pushInterpolationSample (input[numUsed++]); });\r
 \r
-        return ((int) (input - originalIn) + wrap) % wrap;\r
+        return numUsed;\r
     }\r
 \r
-    int interpolateAdding (double speedRatio,\r
-                           const float* input,\r
-                           float* output,\r
-                           int numOutputSamplesToProduce,\r
-                           float gain) noexcept\r
+    template <typename Process, typename PushSample>\r
+    void interpolateImpl (double speedRatio,\r
+                          float* output,\r
+                          int numOutputSamplesToProduce,\r
+                          Process process,\r
+                          PushSample pushSample)\r
     {\r
         auto pos = subSamplePos;\r
-        int numUsed = 0;\r
 \r
-        while (numOutputSamplesToProduce > 0)\r
+        for (auto i = 0; i < numOutputSamplesToProduce; ++i)\r
         {\r
             while (pos >= 1.0)\r
             {\r
-                pushInterpolationSample (input[numUsed++]);\r
+                pushSample();\r
                 pos -= 1.0;\r
             }\r
 \r
-            *output++ += gain * InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer);\r
+            *output = process (*output, InterpolatorTraits::valueAtOffset (lastInputSamples, (float) pos, indexBuffer));\r
+            ++output;\r
             pos += speedRatio;\r
-            --numOutputSamplesToProduce;\r
         }\r
 \r
         subSamplePos = pos;\r
-        return numUsed;\r
     }\r
 \r
     //==============================================================================\r
index 21888b85094245da4fa75a722b285557f1e94eb8..e210705ebddf566690ff9944a59a8e74b8d7dc35 100644 (file)
@@ -229,7 +229,7 @@ public:
     //==============================================================================\r
     /** Constructor. */\r
     SmoothedValue() noexcept\r
-        : SmoothedValue ((FloatType) (std::is_same<SmoothingType, ValueSmoothingTypes::Linear>::value ? 0 : 1))\r
+        : SmoothedValue ((FloatType) (std::is_same_v<SmoothingType, ValueSmoothingTypes::Linear> ? 0 : 1))\r
     {\r
     }\r
 \r
@@ -237,7 +237,7 @@ public:
     SmoothedValue (FloatType initialValue) noexcept\r
     {\r
         // Multiplicative smoothed values cannot ever reach 0!\r
-        jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && initialValue == 0));\r
+        jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && initialValue == 0));\r
 \r
         // Visual Studio can't handle base class initialisation with CRTP\r
         this->currentValue = initialValue;\r
@@ -280,7 +280,7 @@ public:
         }\r
 \r
         // Multiplicative smoothed values cannot ever reach 0!\r
-        jassert (! (std::is_same<SmoothingType, ValueSmoothingTypes::Multiplicative>::value && newValue == 0));\r
+        jassert (! (std::is_same_v<SmoothingType, ValueSmoothingTypes::Multiplicative> && newValue == 0));\r
 \r
         this->target = newValue;\r
         this->countdown = stepsToTarget;\r
@@ -352,49 +352,45 @@ public:
 \r
 private:\r
     //==============================================================================\r
-    template <typename T>\r
-    using LinearVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Linear>::value, void>::type;\r
-\r
-    template <typename T>\r
-    using MultiplicativeVoid = typename std::enable_if <std::is_same <T, ValueSmoothingTypes::Multiplicative>::value, void>::type;\r
-\r
-    //==============================================================================\r
-    template <typename T = SmoothingType>\r
-    LinearVoid<T> setStepSize() noexcept\r
-    {\r
-        step = (this->target - this->currentValue) / (FloatType) this->countdown;\r
-    }\r
-\r
     template <typename T = SmoothingType>\r
-    MultiplicativeVoid<T> setStepSize()\r
+    void setStepSize() noexcept\r
     {\r
-        step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown);\r
+        if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)\r
+        {\r
+            step = (this->target - this->currentValue) / (FloatType) this->countdown;\r
+        }\r
+        else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)\r
+        {\r
+            step = std::exp ((std::log (std::abs (this->target)) - std::log (std::abs (this->currentValue))) / (FloatType) this->countdown);\r
+        }\r
     }\r
 \r
     //==============================================================================\r
     template <typename T = SmoothingType>\r
-    LinearVoid<T> setNextValue() noexcept\r
+    void setNextValue() noexcept\r
     {\r
-        this->currentValue += step;\r
-    }\r
-\r
-    template <typename T = SmoothingType>\r
-    MultiplicativeVoid<T> setNextValue() noexcept\r
-    {\r
-        this->currentValue *= step;\r
+        if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)\r
+        {\r
+            this->currentValue += step;\r
+        }\r
+        else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)\r
+        {\r
+            this->currentValue *= step;\r
+        }\r
     }\r
 \r
     //==============================================================================\r
     template <typename T = SmoothingType>\r
-    LinearVoid<T> skipCurrentValue (int numSamples) noexcept\r
+    void skipCurrentValue (int numSamples) noexcept\r
     {\r
-        this->currentValue += step * (FloatType) numSamples;\r
-    }\r
-\r
-    template <typename T = SmoothingType>\r
-    MultiplicativeVoid<T> skipCurrentValue (int numSamples)\r
-    {\r
-        this->currentValue *= (FloatType) std::pow (step, numSamples);\r
+        if constexpr (std::is_same_v<T, ValueSmoothingTypes::Linear>)\r
+        {\r
+            this->currentValue += step * (FloatType) numSamples;\r
+        }\r
+        else if constexpr (std::is_same_v<T, ValueSmoothingTypes::Multiplicative>)\r
+        {\r
+            this->currentValue *= (FloatType) std::pow (step, numSamples);\r
+        }\r
     }\r
 \r
     //==============================================================================\r
index fa8a59c2d83a4272d8dcf2b5524876e52470ea57..e2645ef018d6d1df544e1697184d410835216529 100644 (file)
@@ -69,9 +69,9 @@ public:
     CallbackHandler (AudioDeviceManager& adm) noexcept  : owner (adm) {}\r
 \r
 private:\r
-    void audioDeviceIOCallbackWithContext (const float** ins,\r
+    void audioDeviceIOCallbackWithContext (const float* const* ins,\r
                                            int numIns,\r
-                                           float** outs,\r
+                                           float* const* outs,\r
                                            int numOuts,\r
                                            int numSamples,\r
                                            const AudioIODeviceCallbackContext& context) override\r
@@ -502,15 +502,90 @@ String AudioDeviceManager::initialiseWithDefaultDevices (int numInputChannelsNee
 \r
 void AudioDeviceManager::insertDefaultDeviceNames (AudioDeviceSetup& setup) const\r
 {\r
+    enum class Direction { out, in };\r
+\r
     if (auto* type = getCurrentDeviceTypeObject())\r
     {\r
-        for (const auto isInput : { false, true })\r
+        // We avoid selecting a device pair that doesn't share a matching sample rate, if possible.\r
+        // If not, other parts of the AudioDeviceManager and AudioIODevice classes should generate\r
+        // an appropriate error message when opening or starting these devices.\r
+        const auto getDevicesToTestForMatchingSampleRate = [&setup, type, this] (Direction dir)\r
         {\r
-            const auto numChannelsNeeded = isInput ? numInputChansNeeded : numOutputChansNeeded;\r
+            const auto isInput = dir == Direction::in;\r
             const auto info = getSetupInfo (setup, isInput);\r
 \r
-            if (numChannelsNeeded > 0 && info.name.isEmpty())\r
-                info.name = type->getDeviceNames (isInput) [type->getDefaultDeviceIndex (isInput)];\r
+            if (! info.name.isEmpty())\r
+                return StringArray { info.name };\r
+\r
+            const auto numChannelsNeeded = isInput ? numInputChansNeeded : numOutputChansNeeded;\r
+            auto deviceNames = numChannelsNeeded > 0 ? type->getDeviceNames (isInput) : StringArray {};\r
+            deviceNames.move (type->getDefaultDeviceIndex (isInput), 0);\r
+\r
+            return deviceNames;\r
+        };\r
+\r
+        std::map<std::pair<Direction, String>, Array<double>> sampleRatesCache;\r
+\r
+        const auto getSupportedSampleRates = [&sampleRatesCache, type] (Direction dir, const String& deviceName)\r
+        {\r
+            const auto key = std::make_pair (dir, deviceName);\r
+\r
+            auto& entry = [&]() -> auto&\r
+            {\r
+                auto it = sampleRatesCache.find (key);\r
+\r
+                if (it != sampleRatesCache.end())\r
+                    return it->second;\r
+\r
+                auto& elem = sampleRatesCache[key];\r
+                auto tempDevice = rawToUniquePtr (type->createDevice ((dir == Direction::in) ? "" : deviceName,\r
+                                                                      (dir == Direction::in) ? deviceName : ""));\r
+                if (tempDevice != nullptr)\r
+                    elem = tempDevice->getAvailableSampleRates();\r
+\r
+                return elem;\r
+            }();\r
+\r
+            return entry;\r
+        };\r
+\r
+        const auto validate = [&getSupportedSampleRates] (const String& outputDeviceName, const String& inputDeviceName)\r
+        {\r
+            jassert (! outputDeviceName.isEmpty() && ! inputDeviceName.isEmpty());\r
+\r
+            const auto outputSampleRates = getSupportedSampleRates (Direction::out, outputDeviceName);\r
+            const auto inputSampleRates  = getSupportedSampleRates (Direction::in,  inputDeviceName);\r
+\r
+            return std::any_of (inputSampleRates.begin(),\r
+                                inputSampleRates.end(),\r
+                                [&] (auto inputSampleRate) { return outputSampleRates.contains (inputSampleRate); });\r
+        };\r
+\r
+        auto outputsToTest = getDevicesToTestForMatchingSampleRate (Direction::out);\r
+        auto inputsToTest  = getDevicesToTestForMatchingSampleRate (Direction::in);\r
+\r
+        // We set default device names, so in case no in-out pair passes the validation, we still\r
+        // produce the same result as before\r
+        if (setup.outputDeviceName.isEmpty() && ! outputsToTest.isEmpty())\r
+            setup.outputDeviceName = outputsToTest[0];\r
+\r
+        if (setup.inputDeviceName.isEmpty() && ! inputsToTest.isEmpty())\r
+            setup.inputDeviceName = inputsToTest[0];\r
+\r
+        // We check all possible in-out pairs until the first validation pass. If no pair passes we\r
+        // leave the setup unchanged.\r
+        for (const auto& out : outputsToTest)\r
+        {\r
+            for (const auto& in : inputsToTest)\r
+            {\r
+                if (validate (out, in))\r
+                {\r
+                    setup.outputDeviceName = out;\r
+                    setup.inputDeviceName  = in;\r
+\r
+                    return;\r
+                }\r
+            }\r
         }\r
     }\r
 }\r
@@ -720,6 +795,12 @@ String AudioDeviceManager::setAudioDeviceSetup (const AudioDeviceSetup& newSetup
         currentDeviceType = currentAudioDevice->getTypeName();\r
 \r
         currentAudioDevice->start (callbackHandler.get());\r
+\r
+        error = currentAudioDevice->getLastError();\r
+    }\r
+\r
+    if (error.isEmpty())\r
+    {\r
         updateCurrentSetup();\r
 \r
         for (int i = 0; i < availableDeviceTypes.size(); ++i)\r
@@ -901,9 +982,9 @@ void AudioDeviceManager::removeAudioCallback (AudioIODeviceCallback* callbackToR
     }\r
 }\r
 \r
-void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelData,\r
+void AudioDeviceManager::audioDeviceIOCallbackInt (const float* const* inputChannelData,\r
                                                    int numInputChannels,\r
-                                                   float** outputChannelData,\r
+                                                   float* const* outputChannelData,\r
                                                    int numOutputChannels,\r
                                                    int numSamples,\r
                                                    const AudioIODeviceCallbackContext& context)\r
@@ -925,7 +1006,7 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat
                                                                      numSamples,\r
                                                                      context);\r
 \r
-        auto** tempChans = tempBuffer.getArrayOfWritePointers();\r
+        auto* const* tempChans = tempBuffer.getArrayOfWritePointers();\r
 \r
         for (int i = callbacks.size(); --i > 0;)\r
         {\r
@@ -967,7 +1048,7 @@ void AudioDeviceManager::audioDeviceIOCallbackInt (const float** inputChannelDat
             testSound.reset();\r
     }\r
 \r
-    outputLevelGetter->updateLevel (const_cast<const float**> (outputChannelData), numOutputChannels, numSamples);\r
+    outputLevelGetter->updateLevel (outputChannelData, numOutputChannels, numSamples);\r
 }\r
 \r
 void AudioDeviceManager::audioDeviceAboutToStartInt (AudioIODevice* const device)\r
@@ -1810,10 +1891,19 @@ private:
         std::function<void()> stopped;\r
         std::function<void()> error;\r
 \r
-        void audioDeviceIOCallback (const float**, int, float**, int, int) override { NullCheckedInvocation::invoke (callback); }\r
-        void audioDeviceAboutToStart (AudioIODevice*)                      override { NullCheckedInvocation::invoke (aboutToStart); }\r
-        void audioDeviceStopped()                                          override { NullCheckedInvocation::invoke (stopped); }\r
-        void audioDeviceError (const String&)                              override { NullCheckedInvocation::invoke (error); }\r
+        void audioDeviceIOCallbackWithContext (const float* const*,\r
+                                               int,\r
+                                               float* const*,\r
+                                               int,\r
+                                               int,\r
+                                               const AudioIODeviceCallbackContext&) override\r
+        {\r
+            NullCheckedInvocation::invoke (callback);\r
+        }\r
+\r
+        void audioDeviceAboutToStart (AudioIODevice*) override { NullCheckedInvocation::invoke (aboutToStart); }\r
+        void audioDeviceStopped()                     override { NullCheckedInvocation::invoke (stopped); }\r
+        void audioDeviceError (const String&)         override { NullCheckedInvocation::invoke (error); }\r
     };\r
 \r
     void initialiseManager (AudioDeviceManager& manager)\r
index f288b6e14b2fc70ec68caf03b788389417e3ce2e..c655254ecff9103f12f547769073b38602d220bd 100644 (file)
@@ -526,9 +526,9 @@ private:
     class CallbackHandler;\r
     std::unique_ptr<CallbackHandler> callbackHandler;\r
 \r
-    void audioDeviceIOCallbackInt (const float** inputChannelData,\r
+    void audioDeviceIOCallbackInt (const float* const* inputChannelData,\r
                                    int totalNumInputChannels,\r
-                                   float** outputChannelData,\r
+                                   float* const* outputChannelData,\r
                                    int totalNumOutputChannels,\r
                                    int numSamples,\r
                                    const AudioIODeviceCallbackContext& context);\r
index 45a83d2b40e1fab14f1095cde9c78ad59a6c0d87..638172860682817dd7530d2d2817a326e35ae750 100644 (file)
 namespace juce\r
 {\r
 \r
+void AudioIODeviceCallback::audioDeviceIOCallbackWithContext ([[maybe_unused]] const float* const* inputChannelData,\r
+                                                              [[maybe_unused]] int numInputChannels,\r
+                                                              [[maybe_unused]] float* const* outputChannelData,\r
+                                                              [[maybe_unused]] int numOutputChannels,\r
+                                                              [[maybe_unused]] int numSamples,\r
+                                                              [[maybe_unused]] const AudioIODeviceCallbackContext& context) {}\r
+\r
+//==============================================================================\r
 AudioIODevice::AudioIODevice (const String& deviceName, const String& deviceTypeName)\r
     : name (deviceName), typeName (deviceTypeName)\r
 {\r
index 8864ffd783ef1d9edd41f8357691a5f7b431327e..1405f7e29d72bc6021058334db0e1433888507ef 100644 (file)
@@ -39,7 +39,7 @@ struct AudioIODeviceCallbackContext
     One of these is passed to an AudioIODevice object to stream the audio data\r
     in and out.\r
 \r
-    The AudioIODevice will repeatedly call this class's audioDeviceIOCallback()\r
+    The AudioIODevice will repeatedly call this class's audioDeviceIOCallbackWithContext()\r
     method on its own high-priority audio thread, when it needs to send or receive\r
     the next block of data.\r
 \r
@@ -90,31 +90,15 @@ public:
                                     processing into several smaller callbacks to ensure higher audio\r
                                     performance. So make sure your code can cope with reasonable\r
                                     changes in the buffer size from one callback to the next.\r
+        @param context              Additional information that may be passed to the\r
+                                    AudioIODeviceCallback.\r
     */\r
-    virtual void audioDeviceIOCallback (const float** inputChannelData,\r
-                                        int numInputChannels,\r
-                                        float** outputChannelData,\r
-                                        int numOutputChannels,\r
-                                        int numSamples)\r
-    {\r
-        ignoreUnused (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples);\r
-    }\r
-\r
-    /** The same as audioDeviceIOCallback(), but with an additional context argument.\r
-\r
-        The default implementation of this function will call audioDeviceIOCallback(),\r
-        but you can override this function if you need to make use of the context information.\r
-    */\r
-    virtual void audioDeviceIOCallbackWithContext (const float** inputChannelData,\r
+    virtual void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
                                                    int numInputChannels,\r
-                                                   float** outputChannelData,\r
+                                                   float* const* outputChannelData,\r
                                                    int numOutputChannels,\r
                                                    int numSamples,\r
-                                                   const AudioIODeviceCallbackContext& context)\r
-    {\r
-        audioDeviceIOCallback (inputChannelData, numInputChannels, outputChannelData, numOutputChannels, numSamples);\r
-        ignoreUnused (context);\r
-    }\r
+                                                   const AudioIODeviceCallbackContext& context);\r
 \r
     /** Called to indicate that the device is about to start calling back.\r
 \r
@@ -142,7 +126,6 @@ public:
     virtual void audioDeviceError (const String& errorMessage);\r
 };\r
 \r
-\r
 //==============================================================================\r
 /**\r
     Base class for an audio device with synchronised input and output channels.\r
index f4b4de0684f7e987faace2fcae7f7901e1ee8e4c..5449282bbc35cececaf77ca0f2772ae3d75c5008 100644 (file)
 //==============================================================================\r
 #elif JUCE_ANDROID\r
 \r
- #include "native/juce_android_Audio.cpp"\r
+namespace juce\r
+{\r
+    using RealtimeThreadFactory = pthread_t (*) (void* (*) (void*), void*);\r
+    RealtimeThreadFactory getAndroidRealtimeThreadFactory();\r
+} // namespace juce\r
+\r
+#include "native/juce_android_Audio.cpp"\r
 \r
  #include <juce_audio_basics/midi/juce_MidiDataConcatenator.h>\r
  #include "native/juce_android_Midi.cpp"\r
 \r
    #include "native/juce_android_Oboe.cpp"\r
   #endif\r
+ #else\r
+// No audio library, so no way to create realtime threads.\r
+  namespace juce\r
+  {\r
+      RealtimeThreadFactory getAndroidRealtimeThreadFactory() { return nullptr; }\r
+  }\r
  #endif\r
 \r
 #endif\r
index 6695c0aca10f4938f20e4cfd50e44ef42abcd4e2..b2685820add4ca1443af68d7b08e01b78e9819c1 100644 (file)
 \r
   ID:                 juce_audio_devices\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE audio and MIDI I/O device classes\r
   description:        Classes to play and record from audio and MIDI I/O devices\r
   website:            http://www.juce.com/juce\r
   license:            ISC\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_audio_basics, juce_events\r
   OSXFrameworks:      CoreAudio CoreMIDI AudioToolbox\r
index 51f0e5af9444840370a13680ba8f9f74a26b00d0..b2baf8c1a1ebd663c5eeeeac637136bf9d0a98d9 100644 (file)
 namespace juce\r
 {\r
 \r
+void MidiInputCallback::handlePartialSysexMessage ([[maybe_unused]] MidiInput* source,\r
+                                                   [[maybe_unused]] const uint8* messageData,\r
+                                                   [[maybe_unused]] int numBytesSoFar,\r
+                                                   [[maybe_unused]] double timestamp) {}\r
+\r
+//==============================================================================\r
 MidiOutput::MidiOutput (const String& deviceName, const String& deviceIdentifier)\r
     : Thread ("midi out"), deviceInfo (deviceName, deviceIdentifier)\r
 {\r
@@ -87,7 +93,7 @@ void MidiOutput::clearAllPendingMessages()
 \r
 void MidiOutput::startBackgroundThread()\r
 {\r
-    startThread (9);\r
+    startThread (Priority::high);\r
 }\r
 \r
 void MidiOutput::stopBackgroundThread()\r
index 814cb7d85d033bba780c630adea9b5a4de2633be..5dab3f9258debdeabd674c4c135e9df3ad81c080 100644 (file)
@@ -225,10 +225,7 @@ public:
     virtual void handlePartialSysexMessage (MidiInput* source,\r
                                             const uint8* messageData,\r
                                             int numBytesSoFar,\r
-                                            double timestamp)\r
-    {\r
-        ignoreUnused (source, messageData, numBytesSoFar, timestamp);\r
-    }\r
+                                            double timestamp);\r
 };\r
 \r
 //==============================================================================\r
index 75607c69161789844c33ff430aceb68c6d90fa00..b654dae640572169e331a4abf370bc4eba6ef1c3 100644 (file)
@@ -253,7 +253,7 @@ public:
             if (inputDevice != nullptr)\r
                 env->CallVoidMethod (inputDevice, AudioRecord.startRecording);\r
 \r
-            startThread (8);\r
+            startThread (Priority::high);\r
         }\r
         else\r
         {\r
index 371ac4c8e21ade7afb816f9023f965e24aab8b15..08825325c8e24607b314a801b866acaccc4a553f 100644 (file)
@@ -327,7 +327,7 @@ static const uint8 javaMidiByteCode[] =
  STATICMETHOD (getAndroidMidiDeviceManager, "getAndroidMidiDeviceManager", "(Landroid/content/Context;)Lcom/rmsl/juce/JuceMidiSupport$MidiDeviceManager;") \\r
  STATICMETHOD (getAndroidBluetoothManager,  "getAndroidBluetoothManager",  "(Landroid/content/Context;)Lcom/rmsl/juce/JuceMidiSupport$BluetoothManager;")\r
 \r
-DECLARE_JNI_CLASS_WITH_BYTECODE (JuceMidiSupport, "com/rmsl/juce/JuceMidiSupport", 23, javaMidiByteCode, sizeof (javaMidiByteCode))\r
+DECLARE_JNI_CLASS_WITH_BYTECODE (JuceMidiSupport, "com/rmsl/juce/JuceMidiSupport", 23, javaMidiByteCode)\r
 #undef JNI_CLASS_MEMBERS\r
 \r
 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
index 105a182a2fbcf12e5f404465f14d5a7c261766b2..42a9efc9154e432ea7ba0e5717677ede7ad908d3 100644 (file)
@@ -423,8 +423,8 @@ private:
         }\r
     }\r
 \r
-    void process (const float** inputChannelData, int numInputChannels,\r
-                  float** outputChannelData, int numOutputChannels, int32_t numFrames)\r
+    void process (const float* const* inputChannelData, int numInputChannels,\r
+                  float* const* outputChannelData, int numOutputChannels, int32_t numFrames)\r
     {\r
         if (auto* cb = callback.exchange (nullptr))\r
         {\r
@@ -596,8 +596,7 @@ private:
         {\r
             if (stream != nullptr)\r
             {\r
-                oboe::Result result = stream->close();\r
-                ignoreUnused (result);\r
+                [[maybe_unused]] oboe::Result result = stream->close();\r
                 JUCE_OBOE_LOG ("Requested Oboe stream close with result: " + getOboeString (result));\r
             }\r
         }\r
@@ -693,14 +692,15 @@ private:
         }\r
 \r
         // Not strictly required as these should not change, but recommended by Google anyway\r
-        void checkStreamSetup (OboeStream* stream, int deviceId, int numChannels, int expectedSampleRate,\r
-                               int expectedBufferSize, oboe::AudioFormat format)\r
+        void checkStreamSetup (OboeStream* stream,\r
+                               [[maybe_unused]] int deviceId,\r
+                               [[maybe_unused]] int numChannels,\r
+                               [[maybe_unused]] int expectedSampleRate,\r
+                               [[maybe_unused]] int expectedBufferSize,\r
+                               oboe::AudioFormat format)\r
         {\r
-            if (auto* nativeStream = stream != nullptr ? stream->getNativeStream() : nullptr)\r
+            if ([[maybe_unused]] auto* nativeStream = stream != nullptr ? stream->getNativeStream() : nullptr)\r
             {\r
-                ignoreUnused (deviceId, numChannels, sampleRate, expectedBufferSize);\r
-                ignoreUnused (streamFormat, bitDepth);\r
-\r
                 jassert (numChannels == 0 || numChannels == nativeStream->getChannelCount());\r
                 jassert (expectedSampleRate == 0 || expectedSampleRate == nativeStream->getSampleRate());\r
                 jassert (format == nativeStream->getFormat());\r
@@ -860,10 +860,8 @@ private:
             return oboe::DataCallbackResult::Continue;\r
         }\r
 \r
-        void printStreamDebugInfo (oboe::AudioStream* stream)\r
+        void printStreamDebugInfo ([[maybe_unused]] oboe::AudioStream* stream)\r
         {\r
-            ignoreUnused (stream);\r
-\r
             JUCE_OBOE_LOG ("\nUses AAudio = " + (stream != nullptr ? String ((int) stream->usesAAudio()) : String ("?"))\r
                  + "\nDirection = " + (stream != nullptr ? getOboeString (stream->getDirection()) : String ("?"))\r
                  + "\nSharingMode = " + (stream != nullptr ? getOboeString (stream->getSharingMode()) : String ("?"))\r
@@ -928,10 +926,8 @@ private:
             return time.tv_sec * oboe::kNanosPerSecond + time.tv_nsec;\r
         }\r
 \r
-        void onErrorBeforeClose (oboe::AudioStream* stream, oboe::Result error) override\r
+        void onErrorBeforeClose (oboe::AudioStream* stream, [[maybe_unused]] oboe::Result error) override\r
         {\r
-            ignoreUnused (error);\r
-\r
             // only output stream should be the master stream receiving callbacks\r
             jassert (stream->getDirection() == oboe::Direction::Output);\r
 \r
@@ -1167,10 +1163,8 @@ public:
 \r
         JUCE_OBOE_LOG ("-----InputDevices:");\r
 \r
-        for (auto& device : inputDevices)\r
+        for ([[maybe_unused]] auto& device : inputDevices)\r
         {\r
-            ignoreUnused (device);\r
-\r
             JUCE_OBOE_LOG ("name = " << device.name);\r
             JUCE_OBOE_LOG ("id = " << String (device.id));\r
             JUCE_OBOE_LOG ("sample rates size = " << String (device.sampleRates.size()));\r
@@ -1179,10 +1173,8 @@ public:
 \r
         JUCE_OBOE_LOG ("-----OutputDevices:");\r
 \r
-        for (auto& device : outputDevices)\r
+        for ([[maybe_unused]] auto& device : outputDevices)\r
         {\r
-            ignoreUnused (device);\r
-\r
             JUCE_OBOE_LOG ("name = " << device.name);\r
             JUCE_OBOE_LOG ("id = " << String (device.id));\r
             JUCE_OBOE_LOG ("sample rates size = " << String (device.sampleRates.size()));\r
@@ -1259,7 +1251,12 @@ public:
             case 22:  return "USB headset";\r
             case 23:  return "hearing aid";\r
             case 24:  return "built-in speaker safe";\r
-            case 25:  return {};\r
+            case 25:  return "remote submix";\r
+            case 26:  return "BLE headset";\r
+            case 27:  return "BLE speaker";\r
+            case 28:  return "echo reference";\r
+            case 29:  return "HDMI eARC";\r
+            case 30:  return "BLE broadcast";\r
             default:  jassertfalse; return {}; // type not supported yet, needs to be added!\r
         }\r
     }\r
@@ -1392,17 +1389,15 @@ public:
         return oboe::DataCallbackResult::Continue;\r
     }\r
 \r
-    void onErrorBeforeClose (oboe::AudioStream*, oboe::Result error) override\r
+    void onErrorBeforeClose (oboe::AudioStream*, [[maybe_unused]] oboe::Result error) override\r
     {\r
         JUCE_OBOE_LOG ("OboeRealtimeThread: Oboe stream onErrorBeforeClose(): " + getOboeString (error));\r
-        ignoreUnused (error);\r
         jassertfalse;  // Should never get here!\r
     }\r
 \r
-    void onErrorAfterClose (oboe::AudioStream*, oboe::Result error) override\r
+    void onErrorAfterClose (oboe::AudioStream*, [[maybe_unused]] oboe::Result error) override\r
     {\r
         JUCE_OBOE_LOG ("OboeRealtimeThread: Oboe stream onErrorAfterClose(): " + getOboeString (error));\r
-        ignoreUnused (error);\r
         jassertfalse;  // Should never get here!\r
     }\r
 \r
@@ -1420,20 +1415,22 @@ private:
 };\r
 \r
 //==============================================================================\r
-pthread_t juce_createRealtimeAudioThread (void* (*entry) (void*), void* userPtr);\r
-pthread_t juce_createRealtimeAudioThread (void* (*entry) (void*), void* userPtr)\r
+RealtimeThreadFactory getAndroidRealtimeThreadFactory()\r
 {\r
-    auto thread = std::make_unique<OboeRealtimeThread>();\r
+    return [] (void* (*entry) (void*), void* userPtr) -> pthread_t\r
+    {\r
+        auto thread = std::make_unique<OboeRealtimeThread>();\r
 \r
-    if (! thread->isOk())\r
-        return {};\r
+        if (! thread->isOk())\r
+            return {};\r
 \r
-    auto threadID = thread->startThread (entry, userPtr);\r
+        auto threadID = thread->startThread (entry, userPtr);\r
 \r
-    // the thread will de-allocate itself\r
-    thread.release();\r
+        // the thread will de-allocate itself\r
+        thread.release();\r
 \r
-    return threadID;\r
+        return threadID;\r
+    };\r
 }\r
 \r
 } // namespace juce\r
index 674f827e70bf313085b8872bb0f688578e7e124d..f0e6d939ac5dee65dbbe8f03e2e86889ae7c67b7 100644 (file)
@@ -601,7 +601,7 @@ public:
             }\r
         }\r
 \r
-        void process (const float** inputChannelData, float** outputChannelData)\r
+        void process (const float* const* inputChannelData, float* const* outputChannelData)\r
         {\r
             if (auto* cb = callback.exchange (nullptr))\r
             {\r
@@ -750,8 +750,8 @@ public:
                     T* recorderBuffer = (inputChannels  > 0 ? recorder->getNextBuffer() : nullptr);\r
                     T* playerBuffer   = (outputChannels > 0 ? player->getNextBuffer()   : nullptr);\r
 \r
-                    const float** inputChannelData = nullptr;\r
-                    float** outputChannelData = nullptr;\r
+                    const float* const* inputChannelData = nullptr;\r
+                    float* const* outputChannelData = nullptr;\r
 \r
                     if (recorderBuffer != nullptr)\r
                     {\r
@@ -1273,20 +1273,22 @@ private:
 };\r
 \r
 //==============================================================================\r
-pthread_t juce_createRealtimeAudioThread (void* (*entry) (void*), void* userPtr);\r
-pthread_t juce_createRealtimeAudioThread (void* (*entry) (void*), void* userPtr)\r
+RealtimeThreadFactory getAndroidRealtimeThreadFactory()\r
 {\r
-    auto thread = std::make_unique<SLRealtimeThread>();\r
+    return [] (void* (*entry) (void*), void* userPtr) -> pthread_t\r
+    {\r
+        auto thread = std::make_unique<SLRealtimeThread>();\r
 \r
-    if (! thread->isOk())\r
-        return {};\r
+        if (! thread->isOk())\r
+            return {};\r
 \r
-    auto threadID = thread->startThread (entry, userPtr);\r
+        auto threadID = thread->startThread (entry, userPtr);\r
 \r
-    // the thread will de-allocate itself\r
-    thread.release();\r
+        // the thread will de-allocate itself\r
+        thread.release();\r
 \r
-    return threadID;\r
+        return threadID;\r
+    };\r
 }\r
 \r
 } // namespace juce\r
index 12c8b3389d081b56b9f341ae370ba7c795b797f1..9789e2a31c1fe87148f4238d8908520c598cb2db 100644 (file)
@@ -579,16 +579,15 @@ struct iOSAudioIODevice::Pimpl      : public AsyncUpdater
             impl.fillHostCallbackInfo (callbackInfo);\r
 \r
             Boolean hostIsPlaying = NO;\r
-            OSStatus err = callbackInfo.transportStateProc2 (callbackInfo.hostUserData,\r
-                                                             &hostIsPlaying,\r
-                                                             nullptr,\r
-                                                             nullptr,\r
-                                                             nullptr,\r
-                                                             nullptr,\r
-                                                             nullptr,\r
-                                                             nullptr);\r
+            [[maybe_unused]] OSStatus err = callbackInfo.transportStateProc2 (callbackInfo.hostUserData,\r
+                                                                              &hostIsPlaying,\r
+                                                                              nullptr,\r
+                                                                              nullptr,\r
+                                                                              nullptr,\r
+                                                                              nullptr,\r
+                                                                              nullptr,\r
+                                                                              nullptr);\r
 \r
-            ignoreUnused (err);\r
             jassert (err == noErr);\r
 \r
             if (hostIsPlaying != shouldSartPlaying)\r
@@ -604,15 +603,14 @@ struct iOSAudioIODevice::Pimpl      : public AsyncUpdater
             impl.fillHostCallbackInfo (callbackInfo);\r
 \r
             Boolean hostIsRecording = NO;\r
-            OSStatus err = callbackInfo.transportStateProc2 (callbackInfo.hostUserData,\r
-                                                             nullptr,\r
-                                                             &hostIsRecording,\r
-                                                             nullptr,\r
-                                                             nullptr,\r
-                                                             nullptr,\r
-                                                             nullptr,\r
-                                                             nullptr);\r
-            ignoreUnused (err);\r
+            [[maybe_unused]] OSStatus err = callbackInfo.transportStateProc2 (callbackInfo.hostUserData,\r
+                                                                              nullptr,\r
+                                                                              &hostIsRecording,\r
+                                                                              nullptr,\r
+                                                                              nullptr,\r
+                                                                              nullptr,\r
+                                                                              nullptr,\r
+                                                                              nullptr);\r
             jassert (err == noErr);\r
 \r
             if (hostIsRecording != shouldStartRecording)\r
@@ -703,12 +701,13 @@ struct iOSAudioIODevice::Pimpl      : public AsyncUpdater
     JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")\r
     Image getIcon (int size)\r
     {\r
+       #if TARGET_OS_MACCATALYST\r
         if (@available (macCatalyst 14.0, *))\r
+       #endif\r
         {\r
             if (interAppAudioConnected)\r
             {\r
-                UIImage* hostUIImage = AudioOutputUnitGetHostIcon (audioUnit, size);\r
-                if (hostUIImage != nullptr)\r
+                if (UIImage* hostUIImage = AudioOutputUnitGetHostIcon (audioUnit, size))\r
                     return juce_createImageFromUIImage (hostUIImage);\r
             }\r
         }\r
@@ -808,11 +807,9 @@ struct iOSAudioIODevice::Pimpl      : public AsyncUpdater
 \r
     void handleAudioUnitPropertyChange (AudioUnit,\r
                                         AudioUnitPropertyID propertyID,\r
-                                        AudioUnitScope scope,\r
-                                        AudioUnitElement element)\r
+                                        [[maybe_unused]] AudioUnitScope scope,\r
+                                        [[maybe_unused]] AudioUnitElement element)\r
     {\r
-        ignoreUnused (scope);\r
-        ignoreUnused (element);\r
         JUCE_IOS_AUDIO_LOG ("handleAudioUnitPropertyChange: propertyID: " << String (propertyID)\r
                                                             << " scope: " << String (scope)\r
                                                           << " element: " << String (element));\r
@@ -834,9 +831,8 @@ struct iOSAudioIODevice::Pimpl      : public AsyncUpdater
     {\r
         UInt32 connected;\r
         UInt32 dataSize = sizeof (connected);\r
-        OSStatus err = AudioUnitGetProperty (audioUnit, kAudioUnitProperty_IsInterAppConnected,\r
-                                             kAudioUnitScope_Global, 0, &connected, &dataSize);\r
-        ignoreUnused (err);\r
+        [[maybe_unused]] OSStatus err = AudioUnitGetProperty (audioUnit, kAudioUnitProperty_IsInterAppConnected,\r
+                                                              kAudioUnitScope_Global, 0, &connected, &dataSize);\r
         jassert (err == noErr);\r
 \r
         JUCE_IOS_AUDIO_LOG ("handleInterAppAudioConnectionChange: " << (connected ? "connected"\r
@@ -892,8 +888,8 @@ struct iOSAudioIODevice::Pimpl      : public AsyncUpdater
             if ((int) numFrames > channelData.getFloatBufferSize())\r
                 channelData.setFloatBufferSize ((int) numFrames);\r
 \r
-            float** const inputData = channelData.audioData.getArrayOfWritePointers();\r
-            float** const outputData = inputData + channelData.inputs->numActiveChannels;\r
+            float* const* const inputData = channelData.audioData.getArrayOfWritePointers();\r
+            float* const* const outputData = inputData + channelData.inputs->numActiveChannels;\r
 \r
             if (useInput)\r
             {\r
@@ -1078,21 +1074,19 @@ struct iOSAudioIODevice::Pimpl      : public AsyncUpdater
     {\r
         zerostruct (callbackInfo);\r
         UInt32 dataSize = sizeof (HostCallbackInfo);\r
-        OSStatus err = AudioUnitGetProperty (audioUnit,\r
-                                             kAudioUnitProperty_HostCallbacks,\r
-                                             kAudioUnitScope_Global,\r
-                                             0,\r
-                                             &callbackInfo,\r
-                                             &dataSize);\r
-        ignoreUnused (err);\r
+        [[maybe_unused]] OSStatus err = AudioUnitGetProperty (audioUnit,\r
+                                                              kAudioUnitProperty_HostCallbacks,\r
+                                                              kAudioUnitScope_Global,\r
+                                                              0,\r
+                                                              &callbackInfo,\r
+                                                              &dataSize);\r
         jassert (err == noErr);\r
     }\r
 \r
     void handleAudioTransportEvent (AudioUnitRemoteControlEvent event)\r
     {\r
-        OSStatus err = AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_RemoteControlToHost,\r
-                                             kAudioUnitScope_Global, 0, &event, sizeof (event));\r
-        ignoreUnused (err);\r
+        [[maybe_unused]] OSStatus err = AudioUnitSetProperty (audioUnit, kAudioOutputUnitProperty_RemoteControlToHost,\r
+                                                              kAudioUnitScope_Global, 0, &event, sizeof (event));\r
         jassert (err == noErr);\r
     }\r
 \r
index dafb34cf956b4d1841ecd85d3adb04efe71d097f..1be927ae90664cd135da796c7f750cfc9f953c30 100644 (file)
@@ -618,7 +618,7 @@ public:
         if (outputDevice != nullptr && JUCE_ALSA_FAILED (snd_pcm_prepare (outputDevice->handle)))\r
             return;\r
 \r
-        startThread (9);\r
+        startThread (Priority::high);\r
 \r
         int count = 1000;\r
 \r
index 8b7e77573bb10b614d870a9a0b483868b8c4e210..4cce7016f9b460dd5a2487a28a2f803fc48f5816 100644 (file)
@@ -462,7 +462,7 @@ private:
         if (callback != nullptr)\r
         {\r
             if ((numActiveInChans + numActiveOutChans) > 0)\r
-                callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inChans.getData()),\r
+                callback->audioDeviceIOCallbackWithContext (inChans.getData(),\r
                                                             numActiveInChans,\r
                                                             outChans,\r
                                                             numActiveOutChans,\r
@@ -544,21 +544,19 @@ private:
         }\r
     }\r
 \r
-    static void infoShutdownCallback (jack_status_t code, const char* reason, void* arg)\r
+    static void infoShutdownCallback (jack_status_t code, [[maybe_unused]] const char* reason, void* arg)\r
     {\r
         jassertquiet (code == 0);\r
 \r
         JUCE_JACK_LOG ("Shutting down with message:");\r
         JUCE_JACK_LOG (reason);\r
-        ignoreUnused (reason);\r
 \r
         shutdownCallback (arg);\r
     }\r
 \r
-    static void errorCallback (const char* msg)\r
+    static void errorCallback ([[maybe_unused]] const char* msg)\r
     {\r
         JUCE_JACK_LOG ("JackAudioIODevice::errorCallback " + String (msg));\r
-        ignoreUnused (msg);\r
     }\r
 \r
     bool deviceIsOpen = false;\r
index b9dfa3e972196c2834e9552e33b9d83b6fceb111..90d54e382b9c439f1ba516b4a13fd505686b96a3 100644 (file)
@@ -41,99 +41,232 @@ constexpr auto juceAudioObjectPropertyElementMain =
        #endif\r
 \r
 //==============================================================================\r
-struct AsyncRestarter\r
+class ManagedAudioBufferList : public AudioBufferList\r
 {\r
-    virtual ~AsyncRestarter() = default;\r
-    virtual void restartAsync() = 0;\r
-};\r
+public:\r
+    struct Deleter\r
+    {\r
+        void operator() (ManagedAudioBufferList* p) const\r
+        {\r
+            if (p != nullptr)\r
+                p->~ManagedAudioBufferList();\r
 \r
-struct SystemVol\r
-{\r
-    SystemVol (AudioObjectPropertySelector selector) noexcept\r
-        : outputDeviceID (kAudioObjectUnknown)\r
+            delete[] reinterpret_cast<std::byte*> (p);\r
+        }\r
+    };\r
+\r
+    using Ref = std::unique_ptr<ManagedAudioBufferList, Deleter>;\r
+\r
+    //==============================================================================\r
+    static Ref create (std::size_t numBuffers)\r
     {\r
-        addr.mScope    = kAudioObjectPropertyScopeGlobal;\r
-        addr.mElement  = juceAudioObjectPropertyElementMain;\r
-        addr.mSelector = kAudioHardwarePropertyDefaultOutputDevice;\r
+        static_assert (alignof (ManagedAudioBufferList) <= alignof (std::max_align_t));\r
 \r
-        if (AudioObjectHasProperty (kAudioObjectSystemObject, &addr))\r
-        {\r
-            UInt32 deviceIDSize = sizeof (outputDeviceID);\r
-            OSStatus status = AudioObjectGetPropertyData (kAudioObjectSystemObject, &addr, 0, nullptr, &deviceIDSize, &outputDeviceID);\r
+        if (std::unique_ptr<std::byte[]> storage { new std::byte[storageSizeForNumBuffers (numBuffers)] })\r
+            return Ref { new (storage.release()) ManagedAudioBufferList (numBuffers) };\r
 \r
-            if (status == noErr)\r
-            {\r
-                addr.mElement  = juceAudioObjectPropertyElementMain;\r
-                addr.mSelector = selector;\r
-                addr.mScope    = kAudioDevicePropertyScopeOutput;\r
+        return nullptr;\r
+    }\r
 \r
-                if (! AudioObjectHasProperty (outputDeviceID, &addr))\r
-                    outputDeviceID = kAudioObjectUnknown;\r
-            }\r
-        }\r
+    //==============================================================================\r
+    static std::size_t storageSizeForNumBuffers (std::size_t numBuffers) noexcept\r
+    {\r
+        return audioBufferListHeaderSize + (numBuffers * sizeof (::AudioBuffer));\r
     }\r
 \r
-    float getGain() const noexcept\r
+    static std::size_t numBuffersForStorageSize (std::size_t bytes) noexcept\r
     {\r
-        Float32 gain = 0;\r
+        bytes -= audioBufferListHeaderSize;\r
 \r
-        if (outputDeviceID != kAudioObjectUnknown)\r
-        {\r
-            UInt32 size = sizeof (gain);\r
-            AudioObjectGetPropertyData (outputDeviceID, &addr,  0, nullptr, &size, &gain);\r
-        }\r
+        // storage size ends between to buffers in AudioBufferList\r
+        jassert ((bytes % sizeof (::AudioBuffer)) == 0);\r
 \r
-        return (float) gain;\r
+        return bytes / sizeof (::AudioBuffer);\r
     }\r
 \r
-    bool setGain (float gain) const noexcept\r
+private:\r
+    // Do not call the base constructor here as this will zero-initialize the first buffer,\r
+    // for which no storage may be available though (when numBuffers == 0).\r
+    explicit ManagedAudioBufferList (std::size_t numBuffers)\r
     {\r
-        if (outputDeviceID != kAudioObjectUnknown && canSetVolume())\r
+        mNumberBuffers = static_cast<UInt32> (numBuffers);\r
+    }\r
+\r
+    static constexpr auto audioBufferListHeaderSize = sizeof (AudioBufferList) - sizeof (::AudioBuffer);\r
+\r
+    JUCE_DECLARE_NON_COPYABLE (ManagedAudioBufferList)\r
+    JUCE_DECLARE_NON_MOVEABLE (ManagedAudioBufferList)\r
+};\r
+\r
+//==============================================================================\r
+struct IgnoreUnused\r
+{\r
+    template <typename... Ts>\r
+    void operator() (Ts&&...) const {}\r
+};\r
+\r
+template <typename T>\r
+static auto getDataPtrAndSize (T& t)\r
+{\r
+    static_assert (std::is_pod_v<T>);\r
+    return std::make_tuple (&t, (UInt32) sizeof (T));\r
+}\r
+\r
+static auto getDataPtrAndSize (ManagedAudioBufferList::Ref& t)\r
+{\r
+    const auto size = t.get() != nullptr\r
+                    ? ManagedAudioBufferList::storageSizeForNumBuffers (t->mNumberBuffers)\r
+                    : 0;\r
+    return std::make_tuple (t.get(), (UInt32) size);\r
+}\r
+\r
+//==============================================================================\r
+[[nodiscard]] static bool audioObjectHasProperty (AudioObjectID objectID, const AudioObjectPropertyAddress address)\r
+{\r
+    return objectID != kAudioObjectUnknown && AudioObjectHasProperty (objectID, &address);\r
+}\r
+\r
+template <typename T, typename OnError = IgnoreUnused>\r
+[[nodiscard]] static auto audioObjectGetProperty (AudioObjectID objectID,\r
+                                                  const AudioObjectPropertyAddress address,\r
+                                                  OnError&& onError = {})\r
+{\r
+    using Result = std::conditional_t<std::is_same_v<T, AudioBufferList>, ManagedAudioBufferList::Ref, std::optional<T>>;\r
+\r
+    if (! audioObjectHasProperty (objectID, address))\r
+        return Result{};\r
+\r
+    auto result = [&]\r
+    {\r
+        if constexpr (std::is_same_v<T, AudioBufferList>)\r
         {\r
-            Float32 newVolume = gain;\r
-            UInt32 size = sizeof (newVolume);\r
+            UInt32 size{};\r
+\r
+            if (auto status = AudioObjectGetPropertyDataSize (objectID, &address, 0, nullptr, &size); status != noErr)\r
+            {\r
+                onError (status);\r
+                return Result{};\r
+            }\r
 \r
-            return AudioObjectSetPropertyData (outputDeviceID, &addr, 0, nullptr, size, &newVolume) == noErr;\r
+            return ManagedAudioBufferList::create (ManagedAudioBufferList::numBuffersForStorageSize (size));\r
         }\r
+        else\r
+        {\r
+            return T{};\r
+        }\r
+    }();\r
+\r
+    auto [ptr, size] = getDataPtrAndSize (result);\r
+\r
+    if (size == 0)\r
+        return Result{};\r
+\r
+    if (auto status = AudioObjectGetPropertyData (objectID, &address, 0, nullptr, &size, ptr); status != noErr)\r
+    {\r
+        onError (status);\r
+        return Result{};\r
+    }\r
+\r
+    return Result { std::move (result) };\r
+}\r
 \r
+template <typename T, typename OnError = IgnoreUnused>\r
+static bool audioObjectSetProperty (AudioObjectID objectID,\r
+                                    const AudioObjectPropertyAddress address,\r
+                                    const T value,\r
+                                    OnError&& onError = {})\r
+{\r
+    if (! audioObjectHasProperty (objectID, address))\r
+        return false;\r
+\r
+    Boolean isSettable = NO;\r
+    if (auto status = AudioObjectIsPropertySettable (objectID, &address, &isSettable); status != noErr)\r
+    {\r
+        onError (status);\r
         return false;\r
     }\r
 \r
-    bool isMuted() const noexcept\r
+    if (! isSettable)\r
+        return false;\r
+\r
+    if (auto status = AudioObjectSetPropertyData (objectID, &address, 0, nullptr, static_cast<UInt32> (sizeof (T)), &value); status != noErr)\r
     {\r
-        UInt32 muted = 0;\r
+        onError (status);\r
+        return false;\r
+    }\r
 \r
-        if (outputDeviceID != kAudioObjectUnknown)\r
-        {\r
-            UInt32 size = sizeof (muted);\r
-            AudioObjectGetPropertyData (outputDeviceID, &addr, 0, nullptr, &size, &muted);\r
-        }\r
+    return true;\r
+}\r
+\r
+template <typename T, typename OnError = IgnoreUnused>\r
+[[nodiscard]] static std::vector<T> audioObjectGetProperties (AudioObjectID objectID,\r
+                                                              const AudioObjectPropertyAddress address,\r
+                                                              OnError&& onError = {})\r
+{\r
+    if (! audioObjectHasProperty (objectID, address))\r
+        return {};\r
+\r
+    UInt32 size{};\r
 \r
-        return muted != 0;\r
+    if (auto status = AudioObjectGetPropertyDataSize (objectID, &address, 0, nullptr, &size); status != noErr)\r
+    {\r
+        onError (status);\r
+        return {};\r
     }\r
 \r
-    bool setMuted (bool mute) const noexcept\r
+    // If this is hit, the number of results is not integral, and the following\r
+    // AudioObjectGetPropertyData will probably write past the end of the result buffer.\r
+    jassert ((size % sizeof (T)) == 0);\r
+    std::vector<T> result (size / sizeof (T));\r
+\r
+    if (auto status = AudioObjectGetPropertyData (objectID, &address, 0, nullptr, &size, result.data()); status != noErr)\r
     {\r
-        if (outputDeviceID != kAudioObjectUnknown && canSetVolume())\r
-        {\r
-            UInt32 newMute = mute ? 1 : 0;\r
-            UInt32 size = sizeof (newMute);\r
+        onError (status);\r
+        return {};\r
+    }\r
 \r
-            return AudioObjectSetPropertyData (outputDeviceID, &addr, 0, nullptr, size, &newMute) == noErr;\r
-        }\r
+    return result;\r
+}\r
 \r
-        return false;\r
+//==============================================================================\r
+struct AsyncRestarter\r
+{\r
+    virtual ~AsyncRestarter() = default;\r
+    virtual void restartAsync() = 0;\r
+};\r
+\r
+struct SystemVol\r
+{\r
+    explicit SystemVol (AudioObjectPropertySelector selector) noexcept\r
+        : outputDeviceID (audioObjectGetProperty<AudioDeviceID> (kAudioObjectSystemObject, { kAudioHardwarePropertyDefaultOutputDevice,\r
+                                                                                             kAudioObjectPropertyScopeGlobal,\r
+                                                                                             juceAudioObjectPropertyElementMain }).value_or (kAudioObjectUnknown)),\r
+          addr { selector, kAudioDevicePropertyScopeOutput, juceAudioObjectPropertyElementMain }\r
+    {}\r
+\r
+    float getGain() const noexcept\r
+    {\r
+        return audioObjectGetProperty<Float32> (outputDeviceID, addr).value_or (0.0f);\r
     }\r
 \r
-private:\r
-    AudioDeviceID outputDeviceID;\r
-    AudioObjectPropertyAddress addr;\r
+    bool setGain (float gain) const noexcept\r
+    {\r
+        return audioObjectSetProperty (outputDeviceID, addr, static_cast<Float32> (gain));\r
+    }\r
+\r
+    bool isMuted() const noexcept\r
+    {\r
+        return audioObjectGetProperty<UInt32> (outputDeviceID, addr).value_or (0) != 0;\r
+    }\r
 \r
-    bool canSetVolume() const noexcept\r
+    bool setMuted (bool mute) const noexcept\r
     {\r
-        Boolean isSettable = NO;\r
-        return AudioObjectIsPropertySettable (outputDeviceID, &addr, &isSettable) == noErr && isSettable;\r
+        return audioObjectSetProperty (outputDeviceID, addr, static_cast<UInt32> (mute ? 1 : 0));\r
     }\r
+\r
+private:\r
+    AudioDeviceID outputDeviceID;\r
+    AudioObjectPropertyAddress addr;\r
 };\r
 \r
 JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
@@ -162,19 +295,25 @@ class CoreAudioIODevice;
 class CoreAudioInternal  : private Timer,\r
                            private AsyncUpdater\r
 {\r
+private:\r
+    // members with deduced return types need to be defined before they\r
+    // are used, so define it here. decltype doesn't help as you can't\r
+    // capture anything in lambdas inside a decltype context.\r
+    auto err2log() const { return [this] (OSStatus err) { OK (err); }; }\r
+\r
 public:\r
-    CoreAudioInternal (CoreAudioIODevice& d, AudioDeviceID id, bool input, bool output)\r
+    CoreAudioInternal (CoreAudioIODevice& d, AudioDeviceID id, bool hasInput, bool hasOutput)\r
         : owner (d),\r
           deviceID (id),\r
-          isInputDevice  (input),\r
-          isOutputDevice (output)\r
+          inStream  (hasInput  ? new Stream (true,  *this, {}) : nullptr),\r
+          outStream (hasOutput ? new Stream (false, *this, {}) : nullptr)\r
     {\r
         jassert (deviceID != 0);\r
 \r
         updateDetailsFromDevice();\r
         JUCE_COREAUDIOLOG ("Creating CoreAudioInternal\n"\r
-                           << (isInputDevice  ? ("    inputDeviceId "  + String (deviceID) + "\n") : "")\r
-                           << (isOutputDevice ? ("    outputDeviceId " + String (deviceID) + "\n") : "")\r
+                           << (inStream  != nullptr ? ("    inputDeviceId "  + String (deviceID) + "\n") : "")\r
+                           << (outStream != nullptr ? ("    outputDeviceId " + String (deviceID) + "\n") : "")\r
                            << getDeviceDetails().joinIntoString ("\n    "));\r
 \r
         AudioObjectPropertyAddress pa;\r
@@ -200,17 +339,20 @@ public:
         stop (false);\r
     }\r
 \r
+    auto getStreams() const { return std::array<Stream*, 2> { { inStream.get(), outStream.get() } }; }\r
+\r
     void allocateTempBuffers()\r
     {\r
         auto tempBufSize = bufferSize + 4;\r
-        audioBuffer.calloc ((numInputChans + numOutputChans) * tempBufSize);\r
 \r
-        tempInputBuffers.calloc  (numInputChans + 2);\r
-        tempOutputBuffers.calloc (numOutputChans + 2);\r
+        auto streams = getStreams();\r
+        const auto total = std::accumulate (streams.begin(), streams.end(), 0,\r
+                                            [] (int n, const auto& s) { return n + (s != nullptr ? s->channels : 0); });\r
+        audioBuffer.calloc (total * tempBufSize);\r
 \r
-        int count = 0;\r
-        for (int i = 0; i < numInputChans;  ++i)  tempInputBuffers[i]  = audioBuffer + count++ * tempBufSize;\r
-        for (int i = 0; i < numOutputChans; ++i)  tempOutputBuffers[i] = audioBuffer + count++ * tempBufSize;\r
+        auto channels = 0;\r
+        for (auto* stream : streams)\r
+            channels += stream != nullptr ? stream->allocateTempBuffers (tempBufSize, channels, audioBuffer) : 0;\r
     }\r
 \r
     struct CallbackDetailsForChannel\r
@@ -220,91 +362,24 @@ public:
         int dataStrideSamples;\r
     };\r
 \r
-    // returns the number of actual available channels\r
-    StringArray getChannelInfo (bool input, Array<CallbackDetailsForChannel>& newChannelInfo) const\r
-    {\r
-        StringArray newNames;\r
-        int chanNum = 0;\r
-        UInt32 size;\r
-\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mSelector = kAudioDevicePropertyStreamConfiguration;\r
-        pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-\r
-        if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size)))\r
-        {\r
-            HeapBlock<AudioBufferList> bufList;\r
-            bufList.calloc (size, 1);\r
-\r
-            if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, bufList)))\r
-            {\r
-                const int numStreams = (int) bufList->mNumberBuffers;\r
-\r
-                for (int i = 0; i < numStreams; ++i)\r
-                {\r
-                    auto& b = bufList->mBuffers[i];\r
-\r
-                    for (unsigned int j = 0; j < b.mNumberChannels; ++j)\r
-                    {\r
-                        String name;\r
-                        NSString* nameNSString = nil;\r
-                        size = sizeof (nameNSString);\r
-\r
-                        pa.mSelector = kAudioObjectPropertyElementName;\r
-                        pa.mElement = (AudioObjectPropertyElement) chanNum + 1;\r
-\r
-                        if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &nameNSString) == noErr)\r
-                        {\r
-                            name = nsStringToJuce (nameNSString);\r
-                            [nameNSString release];\r
-                        }\r
-\r
-                        if ((input ? activeInputChans : activeOutputChans) [chanNum])\r
-                        {\r
-                            CallbackDetailsForChannel info = { i, (int) j, (int) b.mNumberChannels };\r
-                            newChannelInfo.add (info);\r
-                        }\r
-\r
-                        if (name.isEmpty())\r
-                            name << (input ? "Input " : "Output ") << (chanNum + 1);\r
-\r
-                        newNames.add (name);\r
-                        ++chanNum;\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        return newNames;\r
-    }\r
-\r
     Array<double> getSampleRatesFromDevice() const\r
     {\r
         Array<double> newSampleRates;\r
 \r
-        AudioObjectPropertyAddress pa;\r
-        pa.mScope = kAudioObjectPropertyScopeWildcard;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        pa.mSelector = kAudioDevicePropertyAvailableNominalSampleRates;\r
-        UInt32 size = 0;\r
-\r
-        if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size)))\r
+        if (auto ranges = audioObjectGetProperties<AudioValueRange> (deviceID,\r
+                                                                     { kAudioDevicePropertyAvailableNominalSampleRates,\r
+                                                                       kAudioObjectPropertyScopeWildcard,\r
+                                                                       juceAudioObjectPropertyElementMain },\r
+                                                                     err2log()); ! ranges.empty())\r
         {\r
-            HeapBlock<AudioValueRange> ranges;\r
-            ranges.calloc (size, 1);\r
-\r
-            if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges)))\r
+            for (const auto rate : SampleRateHelpers::getAllSampleRates())\r
             {\r
-                for (const auto rate : SampleRateHelpers::getAllSampleRates())\r
+                for (auto range = ranges.rbegin(); range != ranges.rend(); ++range)\r
                 {\r
-                    for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;)\r
+                    if (range->mMinimum - 2 <= rate && rate <= range->mMaximum + 2)\r
                     {\r
-                        if (ranges[j].mMinimum - 2 <= rate && rate <= ranges[j].mMaximum + 2)\r
-                        {\r
-                            newSampleRates.add (rate);\r
-                            break;\r
-                        }\r
+                        newSampleRates.add (rate);\r
+                        break;\r
                     }\r
                 }\r
             }\r
@@ -325,36 +400,27 @@ public:
     {\r
         Array<int> newBufferSizes;\r
 \r
-        AudioObjectPropertyAddress pa;\r
-        pa.mScope = kAudioObjectPropertyScopeWildcard;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        pa.mSelector = kAudioDevicePropertyBufferFrameSizeRange;\r
-        UInt32 size = 0;\r
-\r
-        if (OK (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size)))\r
+        if (auto ranges = audioObjectGetProperties<AudioValueRange> (deviceID, { kAudioDevicePropertyBufferFrameSizeRange,\r
+                                                                                 kAudioObjectPropertyScopeWildcard,\r
+                                                                                 juceAudioObjectPropertyElementMain },\r
+                                                                     err2log()); ! ranges.empty())\r
         {\r
-            HeapBlock<AudioValueRange> ranges;\r
-            ranges.calloc (size, 1);\r
+            newBufferSizes.add ((int) (ranges[0].mMinimum + 15) & ~15);\r
 \r
-            if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, ranges)))\r
+            for (int i = 32; i <= 2048; i += 32)\r
             {\r
-                newBufferSizes.add ((int) (ranges[0].mMinimum + 15) & ~15);\r
-\r
-                for (int i = 32; i <= 2048; i += 32)\r
+                for (auto range = ranges.rbegin(); range != ranges.rend(); ++range)\r
                 {\r
-                    for (int j = size / (int) sizeof (AudioValueRange); --j >= 0;)\r
+                    if (i >= range->mMinimum && i <= range->mMaximum)\r
                     {\r
-                        if (i >= ranges[j].mMinimum && i <= ranges[j].mMaximum)\r
-                        {\r
-                            newBufferSizes.addIfNotAlreadyThere (i);\r
-                            break;\r
-                        }\r
+                        newBufferSizes.addIfNotAlreadyThere (i);\r
+                        break;\r
                     }\r
                 }\r
-\r
-                if (bufferSize > 0)\r
-                    newBufferSizes.addIfNotAlreadyThere (bufferSize);\r
             }\r
+\r
+            if (bufferSize > 0)\r
+                newBufferSizes.addIfNotAlreadyThere (bufferSize);\r
         }\r
 \r
         if (newBufferSizes.isEmpty() && bufferSize > 0)\r
@@ -363,68 +429,22 @@ public:
         return newBufferSizes;\r
     }\r
 \r
-    int getLatencyFromDevice (AudioObjectPropertyScope scope) const\r
-    {\r
-        UInt32 latency = 0;\r
-        UInt32 size = sizeof (latency);\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        pa.mSelector = kAudioDevicePropertyLatency;\r
-        pa.mScope = scope;\r
-        AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &latency);\r
-\r
-        UInt32 safetyOffset = 0;\r
-        size = sizeof (safetyOffset);\r
-        pa.mSelector = kAudioDevicePropertySafetyOffset;\r
-        AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &safetyOffset);\r
-\r
-        return (int) (latency + safetyOffset);\r
-    }\r
-\r
-    int getBitDepthFromDevice (AudioObjectPropertyScope scope) const\r
-    {\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        pa.mSelector = kAudioStreamPropertyPhysicalFormat;\r
-        pa.mScope = scope;\r
-\r
-        AudioStreamBasicDescription asbd;\r
-        UInt32 size = sizeof (asbd);\r
-\r
-        if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &asbd)))\r
-            return (int) asbd.mBitsPerChannel;\r
-\r
-        return 0;\r
-    }\r
-\r
     int getFrameSizeFromDevice() const\r
     {\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mScope = kAudioObjectPropertyScopeWildcard;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        pa.mSelector = kAudioDevicePropertyBufferFrameSize;\r
-\r
-        UInt32 framesPerBuf = (UInt32) bufferSize;\r
-        UInt32 size = sizeof (framesPerBuf);\r
-        AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &framesPerBuf);\r
-        return (int) framesPerBuf;\r
+        return static_cast<int> (audioObjectGetProperty<UInt32> (deviceID, { kAudioDevicePropertyBufferFrameSize,\r
+                                                                             kAudioObjectPropertyScopeWildcard,\r
+                                                                             juceAudioObjectPropertyElementMain }).value_or (0));\r
     }\r
 \r
     bool isDeviceAlive() const\r
     {\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mScope = kAudioObjectPropertyScopeWildcard;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        pa.mSelector = kAudioDevicePropertyDeviceIsAlive;\r
-\r
-        UInt32 isAlive = 0;\r
-        UInt32 size = sizeof (isAlive);\r
         return deviceID != 0\r
-                && OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &isAlive))\r
-                && isAlive != 0;\r
+                 && audioObjectGetProperty<UInt32> (deviceID, { kAudioDevicePropertyDeviceIsAlive,\r
+                                                                kAudioObjectPropertyScopeWildcard,\r
+                                                                juceAudioObjectPropertyElementMain }, err2log()).value_or (0) != 0;\r
     }\r
 \r
-    bool updateDetailsFromDevice()\r
+    bool updateDetailsFromDevice (const BigInteger& activeIns, const BigInteger& activeOuts)\r
     {\r
         stopTimer();\r
 \r
@@ -440,16 +460,10 @@ public:
         auto newBufferSizes = getBufferSizesFromDevice();\r
         auto newSampleRates = getSampleRatesFromDevice();\r
 \r
-        auto newInputLatency  = getLatencyFromDevice (kAudioDevicePropertyScopeInput);\r
-        auto newOutputLatency = getLatencyFromDevice (kAudioDevicePropertyScopeOutput);\r
-\r
-        Array<CallbackDetailsForChannel> newInChans, newOutChans;\r
-        auto newInNames  = isInputDevice  ? getChannelInfo (true,  newInChans)  : StringArray();\r
-        auto newOutNames = isOutputDevice ? getChannelInfo (false, newOutChans) : StringArray();\r
+        auto newInput  = rawToUniquePtr (inStream  != nullptr ? new Stream (true,  *this, activeIns)  : nullptr);\r
+        auto newOutput = rawToUniquePtr (outStream != nullptr ? new Stream (false, *this, activeOuts) : nullptr);\r
 \r
-        auto inputBitDepth  = isInputDevice  ? getBitDepthFromDevice (kAudioDevicePropertyScopeInput)  : 0;\r
-        auto outputBitDepth = isOutputDevice ? getBitDepthFromDevice (kAudioDevicePropertyScopeOutput) : 0;\r
-        auto newBitDepth = jmax (inputBitDepth, outputBitDepth);\r
+        auto newBitDepth = jmax (getBitDepth (newInput), getBitDepth (newOutput));\r
 \r
         {\r
             const ScopedLock sl (callbackLock);\r
@@ -459,21 +473,13 @@ public:
             if (newSampleRate > 0)\r
                 sampleRate = newSampleRate;\r
 \r
-            inputLatency  = newInputLatency;\r
-            outputLatency = newOutputLatency;\r
             bufferSize = newBufferSize;\r
 \r
             sampleRates.swapWith (newSampleRates);\r
             bufferSizes.swapWith (newBufferSizes);\r
 \r
-            inChanNames.swapWith (newInNames);\r
-            outChanNames.swapWith (newOutNames);\r
-\r
-            inputChannelInfo.swapWith (newInChans);\r
-            outputChannelInfo.swapWith (newOutChans);\r
-\r
-            numInputChans  = inputChannelInfo.size();\r
-            numOutputChans = outputChannelInfo.size();\r
+            std::swap (inStream,  newInput);\r
+            std::swap (outStream, newOutput);\r
 \r
             allocateTempBuffers();\r
         }\r
@@ -481,6 +487,11 @@ public:
         return true;\r
     }\r
 \r
+    bool updateDetailsFromDevice()\r
+    {\r
+        return updateDetailsFromDevice (getActiveChannels (inStream), getActiveChannels (outStream));\r
+    }\r
+\r
     StringArray getDeviceDetails()\r
     {\r
         StringArray result;\r
@@ -500,27 +511,33 @@ public:
         result.add (availableBufferSizes);\r
         result.add ("Buffer size: " + String (bufferSize));\r
         result.add ("Bit depth: " + String (bitDepth));\r
-        result.add ("Input latency: " + String (inputLatency));\r
-        result.add ("Output latency: " + String (outputLatency));\r
-        result.add ("Input channel names: "  +  inChanNames.joinIntoString (" "));\r
-        result.add ("Output channel names: " + outChanNames.joinIntoString (" "));\r
+        result.add ("Input latency: "  + String (getLatency (inStream)));\r
+        result.add ("Output latency: " + String (getLatency (outStream)));\r
+        result.add ("Input channel names: "  + getChannelNames (inStream));\r
+        result.add ("Output channel names: " + getChannelNames (outStream));\r
 \r
         return result;\r
     }\r
 \r
+    static auto getScope (bool input)\r
+    {\r
+        return input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
+    }\r
+\r
     //==============================================================================\r
     StringArray getSources (bool input)\r
     {\r
         StringArray s;\r
-        HeapBlock<OSType> types;\r
-        auto num = getAllDataSourcesForDevice (deviceID, types);\r
+        auto types = audioObjectGetProperties<OSType> (deviceID, { kAudioDevicePropertyDataSources,\r
+                                                                   kAudioObjectPropertyScopeWildcard,\r
+                                                                   juceAudioObjectPropertyElementMain });\r
 \r
-        for (int i = 0; i < num; ++i)\r
+        for (auto type : types)\r
         {\r
             AudioValueTranslation avt;\r
             char buffer[256];\r
 \r
-            avt.mInputData = &(types[i]);\r
+            avt.mInputData = &type;\r
             avt.mInputDataSize = sizeof (UInt32);\r
             avt.mOutputData = buffer;\r
             avt.mOutputDataSize = 256;\r
@@ -529,7 +546,7 @@ public:
 \r
             AudioObjectPropertyAddress pa;\r
             pa.mSelector = kAudioDevicePropertyDataSourceNameForID;\r
-            pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
+            pa.mScope = getScope (input);\r
             pa.mElement = juceAudioObjectPropertyElementMain;\r
 \r
             if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &transSize, &avt)))\r
@@ -541,66 +558,48 @@ public:
 \r
     int getCurrentSourceIndex (bool input) const\r
     {\r
-        OSType currentSourceID = 0;\r
-        UInt32 size = sizeof (currentSourceID);\r
-        int result = -1;\r
-\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mSelector = kAudioDevicePropertyDataSource;\r
-        pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-\r
         if (deviceID != 0)\r
         {\r
-            if (OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &currentSourceID)))\r
+            if (auto currentSourceID = audioObjectGetProperty<OSType> (deviceID, { kAudioDevicePropertyDataSource,\r
+                                                                                   getScope (input),\r
+                                                                                   juceAudioObjectPropertyElementMain }, err2log()))\r
             {\r
-                HeapBlock<OSType> types;\r
-                auto num = getAllDataSourcesForDevice (deviceID, types);\r
+                auto types = audioObjectGetProperties<OSType> (deviceID, { kAudioDevicePropertyDataSources,\r
+                                                                           kAudioObjectPropertyScopeWildcard,\r
+                                                                           juceAudioObjectPropertyElementMain });\r
 \r
-                for (int i = 0; i < num; ++i)\r
-                {\r
-                    if (types[num] == currentSourceID)\r
-                    {\r
-                        result = i;\r
-                        break;\r
-                    }\r
-                }\r
+                if (auto it = std::find (types.begin(), types.end(), *currentSourceID); it != types.end())\r
+                    return static_cast<int> (std::distance (types.begin(), it));\r
             }\r
         }\r
 \r
-        return result;\r
+        return -1;\r
     }\r
 \r
     void setCurrentSourceIndex (int index, bool input)\r
     {\r
         if (deviceID != 0)\r
         {\r
-            HeapBlock<OSType> types;\r
-            auto num = getAllDataSourcesForDevice (deviceID, types);\r
+            auto types = audioObjectGetProperties<OSType> (deviceID, { kAudioDevicePropertyDataSources,\r
+                                                                       kAudioObjectPropertyScopeWildcard,\r
+                                                                       juceAudioObjectPropertyElementMain });\r
 \r
-            if (isPositiveAndBelow (index, num))\r
+            if (isPositiveAndBelow (index, static_cast<int> (types.size())))\r
             {\r
-                AudioObjectPropertyAddress pa;\r
-                pa.mSelector = kAudioDevicePropertyDataSource;\r
-                pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
-                pa.mElement = juceAudioObjectPropertyElementMain;\r
-\r
-                OSType typeId = types[index];\r
-\r
-                OK (AudioObjectSetPropertyData (deviceID, &pa, 0, nullptr, sizeof (typeId), &typeId));\r
+                audioObjectSetProperty<OSType> (deviceID, { kAudioDevicePropertyDataSource,\r
+                                                            getScope (input),\r
+                                                            juceAudioObjectPropertyElementMain },\r
+                                                types[static_cast<std::size_t> (index)], err2log());\r
             }\r
         }\r
     }\r
 \r
     double getNominalSampleRate() const\r
     {\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mSelector = kAudioDevicePropertyNominalSampleRate;\r
-        pa.mScope = kAudioObjectPropertyScopeGlobal;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        Float64 sr = 0;\r
-        UInt32 size = (UInt32) sizeof (sr);\r
-        return OK (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, &sr)) ? (double) sr : 0.0;\r
+        return static_cast<double> (audioObjectGetProperty <Float64> (deviceID, { kAudioDevicePropertyNominalSampleRate,\r
+                                                                                  kAudioObjectPropertyScopeGlobal,\r
+                                                                                  juceAudioObjectPropertyElementMain },\r
+                                                                      err2log()).value_or (0.0));\r
     }\r
 \r
     bool setNominalSampleRate (double newSampleRate) const\r
@@ -608,78 +607,52 @@ public:
         if (std::abs (getNominalSampleRate() - newSampleRate) < 1.0)\r
             return true;\r
 \r
-        AudioObjectPropertyAddress pa;\r
-        pa.mSelector = kAudioDevicePropertyNominalSampleRate;\r
-        pa.mScope = kAudioObjectPropertyScopeGlobal;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        Float64 sr = newSampleRate;\r
-        return OK (AudioObjectSetPropertyData (deviceID, &pa, 0, nullptr, sizeof (sr), &sr));\r
+        return audioObjectSetProperty (deviceID, { kAudioDevicePropertyNominalSampleRate,\r
+                                                   kAudioObjectPropertyScopeGlobal,\r
+                                                   juceAudioObjectPropertyElementMain },\r
+                                       static_cast<Float64> (newSampleRate), err2log());\r
     }\r
 \r
     //==============================================================================\r
-    String reopen (const BigInteger& inputChannels,\r
-                   const BigInteger& outputChannels,\r
-                   double newSampleRate, int bufferSizeSamples)\r
+    String reopen (const BigInteger& ins, const BigInteger& outs, double newSampleRate, int bufferSizeSamples)\r
     {\r
-        String error;\r
         callbacksAllowed = false;\r
+        const ScopeGuard scope { [&] { callbacksAllowed = true; } };\r
+\r
         stopTimer();\r
 \r
         stop (false);\r
 \r
-        updateDetailsFromDevice();\r
-\r
-        activeInputChans = inputChannels;\r
-        activeInputChans.setRange (inChanNames.size(),\r
-                                   activeInputChans.getHighestBit() + 1 - inChanNames.size(),\r
-                                   false);\r
-\r
-        activeOutputChans = outputChannels;\r
-        activeOutputChans.setRange (outChanNames.size(),\r
-                                    activeOutputChans.getHighestBit() + 1 - outChanNames.size(),\r
-                                    false);\r
-\r
-        numInputChans = activeInputChans.countNumberOfSetBits();\r
-        numOutputChans = activeOutputChans.countNumberOfSetBits();\r
-\r
         if (! setNominalSampleRate (newSampleRate))\r
         {\r
-            updateDetailsFromDevice();\r
-            error = "Couldn't change sample rate";\r
+            updateDetailsFromDevice (ins, outs);\r
+            return "Couldn't change sample rate";\r
         }\r
-        else\r
+\r
+        if (! audioObjectSetProperty (deviceID, { kAudioDevicePropertyBufferFrameSize,\r
+                                                  kAudioObjectPropertyScopeGlobal,\r
+                                                  juceAudioObjectPropertyElementMain },\r
+                                      static_cast<UInt32> (bufferSizeSamples), err2log()))\r
         {\r
-            // change buffer size\r
-            AudioObjectPropertyAddress pa;\r
-            pa.mSelector = kAudioDevicePropertyBufferFrameSize;\r
-            pa.mScope = kAudioObjectPropertyScopeGlobal;\r
-            pa.mElement = juceAudioObjectPropertyElementMain;\r
-            UInt32 framesPerBuf = (UInt32) bufferSizeSamples;\r
+            updateDetailsFromDevice (ins, outs);\r
+            return "Couldn't change buffer size";\r
+        }\r
 \r
-            if (! OK (AudioObjectSetPropertyData (deviceID, &pa, 0, nullptr, sizeof (framesPerBuf), &framesPerBuf)))\r
-            {\r
-                updateDetailsFromDevice();\r
-                error = "Couldn't change buffer size";\r
-            }\r
-            else\r
-            {\r
-                // Annoyingly, after changing the rate and buffer size, some devices fail to\r
-                // correctly report their new settings until some random time in the future, so\r
-                // after calling updateDetailsFromDevice, we need to manually bodge these values\r
-                // to make sure we're using the correct numbers..\r
-                updateDetailsFromDevice();\r
-                sampleRate = newSampleRate;\r
-                bufferSize = bufferSizeSamples;\r
+        // Annoyingly, after changing the rate and buffer size, some devices fail to\r
+        // correctly report their new settings until some random time in the future, so\r
+        // after calling updateDetailsFromDevice, we need to manually bodge these values\r
+        // to make sure we're using the correct numbers..\r
+        updateDetailsFromDevice (ins, outs);\r
+        sampleRate = newSampleRate;\r
+        bufferSize = bufferSizeSamples;\r
 \r
-                if (sampleRates.size() == 0)\r
-                    error = "Device has no available sample-rates";\r
-                else if (bufferSizes.size() == 0)\r
-                    error = "Device has no available buffer-sizes";\r
-            }\r
-        }\r
+        if (sampleRates.size() == 0)\r
+            return "Device has no available sample-rates";\r
 \r
-        callbacksAllowed = true;\r
-        return error;\r
+        if (bufferSizes.size() == 0)\r
+            return "Device has no available buffer-sizes";\r
+\r
+        return {};\r
     }\r
 \r
     bool start (AudioIODeviceCallback* callbackToNotify)\r
@@ -692,28 +665,42 @@ public:
             callback->audioDeviceAboutToStart (&owner);\r
         }\r
 \r
-        if (! started)\r
+        for (auto* stream : getStreams())\r
+            if (stream != nullptr)\r
+                stream->previousSampleTime = invalidSampleTime;\r
+\r
+        owner.hadDiscontinuity = false;\r
+\r
+        if (scopedProcID.get() == nullptr && deviceID != 0)\r
         {\r
-            if (deviceID != 0)\r
+            scopedProcID = [&self = *this,\r
+                            &lock = callbackLock,\r
+                            nextProcID = ScopedAudioDeviceIOProcID { *this, deviceID, audioIOProc },\r
+                            deviceID = deviceID]() mutable -> ScopedAudioDeviceIOProcID\r
             {\r
-                if (OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, this, &audioProcID)))\r
+                // It *looks* like AudioDeviceStart may start the audio callback running, and then\r
+                // immediately lock an internal mutex.\r
+                // The same mutex is locked before calling the audioIOProc.\r
+                // If we get very unlucky, then we can end up with thread A taking the callbackLock\r
+                // and calling AudioDeviceStart, followed by thread B taking the CoreAudio lock\r
+                // and calling into audioIOProc, which waits on the callbackLock. When thread A\r
+                // continues it attempts to take the CoreAudio lock, and the program deadlocks.\r
+\r
+                if (auto* procID = nextProcID.get())\r
                 {\r
-                    if (OK (AudioDeviceStart (deviceID, audioProcID)))\r
-                    {\r
-                        started = true;\r
-                    }\r
-                    else\r
-                    {\r
-                        OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID));\r
-                        audioProcID = {};\r
-                    }\r
+                    const ScopedUnlock su (lock);\r
+\r
+                    if (self.OK (AudioDeviceStart (deviceID, procID)))\r
+                        return std::move (nextProcID);\r
                 }\r
-            }\r
+\r
+                return {};\r
+            }();\r
         }\r
 \r
-        playing = started && callback != nullptr;\r
+        playing = scopedProcID.get() != nullptr && callback != nullptr;\r
 \r
-        return started;\r
+        return scopedProcID.get() != nullptr;\r
     }\r
 \r
     AudioIODeviceCallback* stop (bool leaveInterruptRunning)\r
@@ -722,7 +709,7 @@ public:
 \r
         auto result = std::exchange (callback, nullptr);\r
 \r
-        if (started && (deviceID != 0) && ! leaveInterruptRunning)\r
+        if (scopedProcID.get() != nullptr && (deviceID != 0) && ! leaveInterruptRunning)\r
         {\r
             audioDeviceStopPending = true;\r
 \r
@@ -736,9 +723,7 @@ public:
                 Thread::sleep (50);\r
             }\r
 \r
-            OK (AudioDeviceDestroyIOProcID (deviceID, audioProcID));\r
-            audioProcID = {};\r
-            started = false;\r
+            scopedProcID = {};\r
             playing = false;\r
         }\r
 \r
@@ -748,7 +733,8 @@ public:
     double getSampleRate() const  { return sampleRate; }\r
     int getBufferSize() const     { return bufferSize; }\r
 \r
-    void audioCallback (const AudioTimeStamp* timeStamp,\r
+    void audioCallback (const AudioTimeStamp* inputTimestamp,\r
+                        const AudioTimeStamp* outputTimestamp,\r
                         const AudioBufferList* inInputData,\r
                         AudioBufferList* outOutputData)\r
     {\r
@@ -756,18 +742,21 @@ public:
 \r
         if (audioDeviceStopPending)\r
         {\r
-            if (OK (AudioDeviceStop (deviceID, audioProcID)))\r
+            if (OK (AudioDeviceStop (deviceID, scopedProcID.get())))\r
                 audioDeviceStopPending = false;\r
 \r
             return;\r
         }\r
 \r
+        const auto numInputChans  = getChannels (inStream);\r
+        const auto numOutputChans = getChannels (outStream);\r
+\r
         if (callback != nullptr)\r
         {\r
             for (int i = numInputChans; --i >= 0;)\r
             {\r
-                auto& info = inputChannelInfo.getReference(i);\r
-                auto dest = tempInputBuffers[i];\r
+                auto& info = inStream->channelInfo.getReference (i);\r
+                auto dest = inStream->tempBuffers[i];\r
                 auto src = ((const float*) inInputData->mBuffers[info.streamNum].mData) + info.dataOffsetSamples;\r
                 auto stride = info.dataStrideSamples;\r
 \r
@@ -781,19 +770,23 @@ public:
                 }\r
             }\r
 \r
+            for (auto* stream : getStreams())\r
+                if (stream != nullptr)\r
+                    owner.hadDiscontinuity |= stream->checkTimestampsForDiscontinuity (stream == inStream.get() ? inputTimestamp\r
+                                                                                                                : outputTimestamp);\r
+\r
+            const auto* timeStamp = numOutputChans > 0 ? outputTimestamp : inputTimestamp;\r
             const auto nanos = timeStamp != nullptr ? timeConversions.hostTimeToNanos (timeStamp->mHostTime) : 0;\r
 \r
-            callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (tempInputBuffers.get()),\r
-                                                        numInputChans,\r
-                                                        tempOutputBuffers,\r
-                                                        numOutputChans,\r
+            callback->audioDeviceIOCallbackWithContext (getTempBuffers (inStream),  numInputChans,\r
+                                                        getTempBuffers (outStream), numOutputChans,\r
                                                         bufferSize,\r
                                                         { timeStamp != nullptr ? &nanos : nullptr });\r
 \r
             for (int i = numOutputChans; --i >= 0;)\r
             {\r
-                auto& info = outputChannelInfo.getReference (i);\r
-                auto src = tempOutputBuffers[i];\r
+                auto& info = outStream->channelInfo.getReference (i);\r
+                auto src = outStream->tempBuffers[i];\r
                 auto dest = ((float*) outOutputData->mBuffers[info.streamNum].mData) + info.dataOffsetSamples;\r
                 auto stride = info.dataStrideSamples;\r
 \r
@@ -813,6 +806,10 @@ public:
                 zeromem (outOutputData->mBuffers[i].mData,\r
                          outOutputData->mBuffers[i].mDataByteSize);\r
         }\r
+\r
+        for (auto* stream : getStreams())\r
+            if (stream != nullptr)\r
+                stream->previousSampleTime += static_cast<Float64> (bufferSize);\r
     }\r
 \r
     // called by callbacks (possibly off the main thread)\r
@@ -832,34 +829,256 @@ public:
     bool isPlaying() const { return playing.load(); }\r
 \r
     //==============================================================================\r
+    struct Stream\r
+    {\r
+        Stream (bool isInput, CoreAudioInternal& parent, const BigInteger& activeRequested)\r
+            : input (isInput),\r
+              latency (getLatencyFromDevice (isInput, parent)),\r
+              bitDepth (getBitDepthFromDevice (isInput, parent)),\r
+              chanNames (getChannelNames (isInput, parent)),\r
+              activeChans ([&activeRequested, clearFrom = chanNames.size()]\r
+                           {\r
+                               auto result = activeRequested;\r
+                               result.setRange (clearFrom, result.getHighestBit() + 1 - clearFrom, false);\r
+                               return result;\r
+                           }()),\r
+              channelInfo (getChannelInfos (isInput, parent, activeChans)),\r
+              channels (static_cast<int> (channelInfo.size()))\r
+        {}\r
+\r
+        int allocateTempBuffers (int tempBufSize, int channelCount, HeapBlock<float>& buffer)\r
+        {\r
+            tempBuffers.calloc (channels + 2);\r
+\r
+            for (int i = 0; i < channels;  ++i)\r
+                tempBuffers[i] = buffer + channelCount++ * tempBufSize;\r
+\r
+            return channels;\r
+        }\r
+\r
+        template <typename Visitor>\r
+        static auto visitChannels (bool isInput, CoreAudioInternal& parent, Visitor&& visitor)\r
+        {\r
+            struct Args { int stream, channelIdx, chanNum, streamChannels; };\r
+            using VisitorResultType = typename std::invoke_result_t<Visitor, const Args&>::value_type;\r
+            Array<VisitorResultType> result;\r
+            int chanNum = 0;\r
+\r
+            if (auto bufList = audioObjectGetProperty<AudioBufferList> (parent.deviceID, { kAudioDevicePropertyStreamConfiguration,\r
+                                                                                           getScope (isInput),\r
+                                                                                           juceAudioObjectPropertyElementMain }, parent.err2log()))\r
+            {\r
+                const int numStreams = static_cast<int> (bufList->mNumberBuffers);\r
+\r
+                for (int i = 0; i < numStreams; ++i)\r
+                {\r
+                    auto& b = bufList->mBuffers[i];\r
+\r
+                    for (unsigned int j = 0; j < b.mNumberChannels; ++j)\r
+                    {\r
+                        // Passing an anonymous struct ensures that callback can't confuse the argument order\r
+                        if (auto opt = visitor (Args { i, static_cast<int> (j), chanNum++, static_cast<int> (b.mNumberChannels) }))\r
+                            result.add (std::move (*opt));\r
+                    }\r
+                }\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        static Array<CallbackDetailsForChannel> getChannelInfos (bool isInput, CoreAudioInternal& parent, const BigInteger& active)\r
+        {\r
+            return visitChannels (isInput, parent,\r
+                                  [&] (const auto& args) -> std::optional<CallbackDetailsForChannel>\r
+                                  {\r
+                                      if (! active[args.chanNum])\r
+                                          return {};\r
+\r
+                                      return CallbackDetailsForChannel { args.stream, args.channelIdx, args.streamChannels };\r
+                                  });\r
+        }\r
+\r
+        static StringArray getChannelNames (bool isInput, CoreAudioInternal& parent)\r
+        {\r
+            auto names = visitChannels (isInput, parent,\r
+                                        [&] (const auto& args) -> std::optional<String>\r
+                                        {\r
+                                            String name;\r
+                                            const auto element = static_cast<AudioObjectPropertyElement> (args.chanNum + 1);\r
+\r
+                                            if (auto nameNSString = audioObjectGetProperty<NSString*> (parent.deviceID, { kAudioObjectPropertyElementName,\r
+                                                                                                                          getScope (isInput),\r
+                                                                                                                          element }).value_or (nullptr))\r
+                                            {\r
+                                                name = nsStringToJuce (nameNSString);\r
+                                                [nameNSString release];\r
+                                            }\r
+\r
+                                            if (name.isEmpty())\r
+                                                name << (isInput ? "Input " : "Output ") << (args.chanNum + 1);\r
+\r
+                                            return name;\r
+                                        });\r
+\r
+            return { names };\r
+        }\r
+\r
+        static int getBitDepthFromDevice (bool isInput, CoreAudioInternal& parent)\r
+        {\r
+            return static_cast<int> (audioObjectGetProperty<AudioStreamBasicDescription> (parent.deviceID, { kAudioStreamPropertyPhysicalFormat,\r
+                                                                                                             getScope (isInput),\r
+                                                                                                             juceAudioObjectPropertyElementMain }, parent.err2log())\r
+                                                                                         .value_or (AudioStreamBasicDescription{}).mBitsPerChannel);\r
+        }\r
+\r
+        static int getLatencyFromDevice (bool isInput, CoreAudioInternal& parent)\r
+        {\r
+            const auto scope = getScope (isInput);\r
+\r
+            const auto deviceLatency  = audioObjectGetProperty<UInt32> (parent.deviceID, { kAudioDevicePropertyLatency,\r
+                                                                                           scope,\r
+                                                                                           juceAudioObjectPropertyElementMain }).value_or (0);\r
+\r
+            const auto safetyOffset   = audioObjectGetProperty<UInt32> (parent.deviceID, { kAudioDevicePropertySafetyOffset,\r
+                                                                                           scope,\r
+                                                                                           juceAudioObjectPropertyElementMain }).value_or (0);\r
+\r
+            const auto framesInBuffer = audioObjectGetProperty<UInt32> (parent.deviceID, { kAudioDevicePropertyBufferFrameSize,\r
+                                                                                           kAudioObjectPropertyScopeWildcard,\r
+                                                                                           juceAudioObjectPropertyElementMain }).value_or (0);\r
+\r
+            UInt32 streamLatency = 0;\r
+\r
+            if (auto streams = audioObjectGetProperties<AudioStreamID> (parent.deviceID, { kAudioDevicePropertyStreams,\r
+                                                                                           scope,\r
+                                                                                           juceAudioObjectPropertyElementMain }); ! streams.empty())\r
+                streamLatency = audioObjectGetProperty<UInt32> (streams.front(), { kAudioStreamPropertyLatency,\r
+                                                                                   scope,\r
+                                                                                   juceAudioObjectPropertyElementMain }).value_or (0);\r
+\r
+            return static_cast<int> (deviceLatency + safetyOffset + framesInBuffer + streamLatency);\r
+        }\r
+\r
+        bool checkTimestampsForDiscontinuity (const AudioTimeStamp* timestamp) noexcept\r
+        {\r
+            if (channels > 0)\r
+            {\r
+                jassert (timestamp == nullptr || (((timestamp->mFlags & kAudioTimeStampSampleTimeValid) != 0)\r
+                                               && ((timestamp->mFlags & kAudioTimeStampHostTimeValid)   != 0)));\r
+\r
+                if (previousSampleTime == invalidSampleTime)\r
+                    previousSampleTime = timestamp != nullptr ? timestamp->mSampleTime : 0.0;\r
+\r
+                if (timestamp != nullptr && std::fabs (previousSampleTime - timestamp->mSampleTime) >= 1.0)\r
+                {\r
+                    previousSampleTime = timestamp->mSampleTime;\r
+                    return true;\r
+                }\r
+            }\r
+\r
+            return false;\r
+        }\r
+\r
+        //==============================================================================\r
+        const bool input;\r
+        const int latency;\r
+        const int bitDepth;\r
+        const StringArray chanNames;\r
+        const BigInteger activeChans;\r
+        const Array<CallbackDetailsForChannel> channelInfo;\r
+        const int channels = 0;\r
+        Float64 previousSampleTime;\r
+\r
+        HeapBlock<float*> tempBuffers;\r
+\r
+        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Stream)\r
+    };\r
+\r
+    template <typename Callback>\r
+    static auto getWithDefault (const std::unique_ptr<Stream>& ptr, Callback&& callback)\r
+    {\r
+        return ptr != nullptr ? callback (*ptr) : decltype (callback (*ptr)) {};\r
+    }\r
+\r
+    template <typename Value>\r
+    static auto getWithDefault (const std::unique_ptr<Stream>& ptr, Value (Stream::* member))\r
+    {\r
+        return getWithDefault (ptr, [&] (Stream& s) { return s.*member; });\r
+    }\r
+\r
+    static int          getLatency          (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::latency); }\r
+    static int          getBitDepth         (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::bitDepth); }\r
+    static int          getChannels         (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::channels); }\r
+    static int          getNumChannelNames  (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::chanNames).size(); }\r
+    static String       getChannelNames     (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::chanNames).joinIntoString (" "); }\r
+    static BigInteger   getActiveChannels   (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, &Stream::activeChans); }\r
+    static float**      getTempBuffers      (const std::unique_ptr<Stream>& ptr) { return getWithDefault (ptr, [] (auto& s) { return s.tempBuffers.get(); }); }\r
+\r
+    //==============================================================================\r
+    static constexpr Float64 invalidSampleTime = std::numeric_limits<Float64>::max();\r
+\r
     CoreAudioIODevice& owner;\r
-    int inputLatency  = 0;\r
-    int outputLatency = 0;\r
     int bitDepth = 32;\r
     int xruns = 0;\r
-    BigInteger activeInputChans, activeOutputChans;\r
-    StringArray inChanNames, outChanNames;\r
     Array<double> sampleRates;\r
     Array<int> bufferSizes;\r
-    AudioDeviceIOProcID audioProcID = {};\r
+    AudioDeviceID deviceID;\r
+    std::unique_ptr<Stream> inStream, outStream;\r
 \r
 private:\r
+    class ScopedAudioDeviceIOProcID\r
+    {\r
+    public:\r
+        ScopedAudioDeviceIOProcID() = default;\r
+\r
+        ScopedAudioDeviceIOProcID (CoreAudioInternal& coreAudio, AudioDeviceID d, AudioDeviceIOProc audioIOProc)\r
+            : deviceID (d)\r
+        {\r
+            if (! coreAudio.OK (AudioDeviceCreateIOProcID (deviceID, audioIOProc, &coreAudio, &proc)))\r
+                proc = {};\r
+        }\r
+\r
+        ~ScopedAudioDeviceIOProcID() noexcept\r
+        {\r
+            if (proc != AudioDeviceIOProcID{})\r
+                AudioDeviceDestroyIOProcID (deviceID, proc);\r
+        }\r
+\r
+        ScopedAudioDeviceIOProcID (ScopedAudioDeviceIOProcID&& other) noexcept\r
+        {\r
+            swap (other);\r
+        }\r
+\r
+        ScopedAudioDeviceIOProcID& operator= (ScopedAudioDeviceIOProcID&& other) noexcept\r
+        {\r
+            ScopedAudioDeviceIOProcID { std::move (other) }.swap (*this);\r
+            return *this;\r
+        }\r
+\r
+        AudioDeviceIOProcID get() const { return proc; }\r
+\r
+    private:\r
+        void swap (ScopedAudioDeviceIOProcID& other) noexcept\r
+        {\r
+            std::swap (other.deviceID, deviceID);\r
+            std::swap (other.proc, proc);\r
+        }\r
+\r
+        AudioDeviceID deviceID = {};\r
+        AudioDeviceIOProcID proc = {};\r
+    };\r
+\r
+    //==============================================================================\r
+    ScopedAudioDeviceIOProcID scopedProcID;\r
     CoreAudioTimeConversions timeConversions;\r
     AudioIODeviceCallback* callback = nullptr;\r
     CriticalSection callbackLock;\r
-    AudioDeviceID deviceID;\r
-    bool started = false, audioDeviceStopPending = false;\r
+    bool audioDeviceStopPending = false;\r
     std::atomic<bool> playing { false };\r
     double sampleRate = 0;\r
     int bufferSize = 0;\r
     HeapBlock<float> audioBuffer;\r
-    int numInputChans  = 0;\r
-    int numOutputChans = 0;\r
     Atomic<int> callbacksAllowed { 1 };\r
-    const bool isInputDevice, isOutputDevice;\r
-\r
-    Array<CallbackDetailsForChannel> inputChannelInfo, outputChannelInfo;\r
-    HeapBlock<float*> tempInputBuffers, tempOutputBuffers;\r
 \r
     //==============================================================================\r
     void timerCallback() override\r
@@ -883,14 +1102,14 @@ private:
     }\r
 \r
     static OSStatus audioIOProc (AudioDeviceID /*inDevice*/,\r
-                                 const AudioTimeStamp* inNow,\r
+                                 [[maybe_unused]] const AudioTimeStamp* inNow,\r
                                  const AudioBufferList* inInputData,\r
-                                 const AudioTimeStamp* /*inInputTime*/,\r
+                                 const AudioTimeStamp* inInputTime,\r
                                  AudioBufferList* outOutputData,\r
-                                 const AudioTimeStamp* /*inOutputTime*/,\r
+                                 const AudioTimeStamp* inOutputTime,\r
                                  void* device)\r
     {\r
-        static_cast<CoreAudioInternal*> (device)->audioCallback (inNow, inInputData, outOutputData);\r
+        static_cast<CoreAudioInternal*> (device)->audioCallback (inInputTime, inOutputTime, inInputData, outOutputData);\r
         return noErr;\r
     }\r
 \r
@@ -932,26 +1151,6 @@ private:
     }\r
 \r
     //==============================================================================\r
-    static int getAllDataSourcesForDevice (AudioDeviceID deviceID, HeapBlock<OSType>& types)\r
-    {\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mSelector = kAudioDevicePropertyDataSources;\r
-        pa.mScope = kAudioObjectPropertyScopeWildcard;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
-        UInt32 size = 0;\r
-\r
-        if (deviceID != 0\r
-             && AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size) == noErr)\r
-        {\r
-            types.calloc (size, 1);\r
-\r
-            if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, types) == noErr)\r
-                return size / (int) sizeof (OSType);\r
-        }\r
-\r
-        return 0;\r
-    }\r
-\r
     bool OK (const OSStatus errorCode) const\r
     {\r
         if (errorCode == noErr)\r
@@ -1017,8 +1216,8 @@ public:
         AudioObjectRemovePropertyListener (kAudioObjectSystemObject, &pa, hardwareListenerProc, internal.get());\r
     }\r
 \r
-    StringArray getOutputChannelNames() override        { return internal->outChanNames; }\r
-    StringArray getInputChannelNames() override         { return internal->inChanNames; }\r
+    StringArray getOutputChannelNames() override        { return internal->outStream != nullptr ? internal->outStream->chanNames : StringArray(); }\r
+    StringArray getInputChannelNames() override         { return internal->inStream  != nullptr ? internal->inStream ->chanNames : StringArray(); }\r
 \r
     bool isOpen() override                              { return isOpen_; }\r
 \r
@@ -1030,12 +1229,14 @@ public:
     int getCurrentBufferSizeSamples() override          { return internal->getBufferSize(); }\r
     int getXRunCount() const noexcept override          { return internal->xruns; }\r
 \r
+    int getIndexOfDevice (bool asInput) const           { return asInput ? inputIndex : outputIndex; }\r
+\r
     int getDefaultBufferSize() override\r
     {\r
         int best = 0;\r
 \r
         for (int i = 0; best < 512 && i < internal->bufferSizes.size(); ++i)\r
-            best = internal->bufferSizes.getUnchecked(i);\r
+            best = internal->bufferSizes.getUnchecked (i);\r
 \r
         if (best == 0)\r
             best = 512;\r
@@ -1073,21 +1274,10 @@ public:
         internal->stop (false);\r
     }\r
 \r
-    BigInteger getActiveOutputChannels() const override     { return internal->activeOutputChans; }\r
-    BigInteger getActiveInputChannels() const override      { return internal->activeInputChans; }\r
-\r
-    int getOutputLatencyInSamples() override\r
-    {\r
-        // this seems like a good guess at getting the latency right - comparing\r
-        // this with a round-trip measurement, it gets it to within a few millisecs\r
-        // for the built-in mac soundcard\r
-        return internal->outputLatency;\r
-    }\r
-\r
-    int getInputLatencyInSamples() override\r
-    {\r
-        return internal->inputLatency;\r
-    }\r
+    BigInteger getActiveOutputChannels()      const override { return CoreAudioInternal::getActiveChannels (internal->outStream); }\r
+    BigInteger getActiveInputChannels()       const override { return CoreAudioInternal::getActiveChannels (internal->inStream); }\r
+    int getOutputLatencyInSamples()                 override { return CoreAudioInternal::getLatency (internal->outStream); }\r
+    int getInputLatencyInSamples()                  override { return CoreAudioInternal::getLatency (internal->inStream); }\r
 \r
     void start (AudioIODeviceCallback* callback) override\r
     {\r
@@ -1164,6 +1354,7 @@ public:
 \r
     WeakReference<CoreAudioIODeviceType> deviceType;\r
     int inputIndex, outputIndex;\r
+    bool hadDiscontinuity;\r
 \r
 private:\r
     std::unique_ptr<CoreAudioInternal> internal;\r
@@ -1207,82 +1398,48 @@ private:
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (CoreAudioIODevice)\r
 };\r
 \r
+\r
 //==============================================================================\r
 class AudioIODeviceCombiner    : public AudioIODevice,\r
                                  private AsyncRestarter,\r
-                                 private Thread,\r
                                  private Timer\r
 {\r
 public:\r
-    AudioIODeviceCombiner (const String& deviceName, CoreAudioIODeviceType* deviceType)\r
+    AudioIODeviceCombiner (const String& deviceName, CoreAudioIODeviceType* deviceType,\r
+                           std::unique_ptr<CoreAudioIODevice>&& inputDevice,\r
+                           std::unique_ptr<CoreAudioIODevice>&& outputDevice)\r
         : AudioIODevice (deviceName, "CoreAudio"),\r
-          Thread (deviceName),\r
-          owner (deviceType)\r
+          owner (deviceType),\r
+          currentSampleRate (inputDevice->getCurrentSampleRate()),\r
+          currentBufferSize (inputDevice->getCurrentBufferSizeSamples()),\r
+          inputWrapper  (*this, std::move (inputDevice),  true),\r
+          outputWrapper (*this, std::move (outputDevice), false)\r
     {\r
+        if (getAvailableSampleRates().isEmpty())\r
+            lastError = TRANS("The input and output devices don't share a common sample rate!");\r
     }\r
 \r
     ~AudioIODeviceCombiner() override\r
     {\r
         close();\r
-        devices.clear();\r
-    }\r
-\r
-    void addDevice (std::unique_ptr<CoreAudioIODevice> device, bool useInputs, bool useOutputs)\r
-    {\r
-        jassert (device != nullptr);\r
-        jassert (! isOpen());\r
-        jassert (! device->isOpen());\r
-        auto* devicePtr = device.get();\r
-\r
-        devices.add (std::make_unique<DeviceWrapper> (*this, std::move (device), useInputs, useOutputs));\r
-\r
-        if (currentSampleRate == 0)\r
-            currentSampleRate = devicePtr->getCurrentSampleRate();\r
-\r
-        if (currentBufferSize == 0)\r
-            currentBufferSize = devicePtr->getCurrentBufferSizeSamples();\r
-    }\r
-\r
-    Array<AudioIODevice*> getDevices() const\r
-    {\r
-        Array<AudioIODevice*> devs;\r
-\r
-        for (auto* d : devices)\r
-            devs.add (d->device.get());\r
-\r
-        return devs;\r
     }\r
 \r
-    StringArray getOutputChannelNames() override\r
-    {\r
-        StringArray names;\r
-\r
-        for (auto* d : devices)\r
-            names.addArray (d->getOutputChannelNames());\r
-\r
-        names.appendNumbersToDuplicates (false, true);\r
-        return names;\r
-    }\r
+    auto getDeviceWrappers()       { return std::array<      DeviceWrapper*, 2> { { &inputWrapper, &outputWrapper } }; }\r
+    auto getDeviceWrappers() const { return std::array<const DeviceWrapper*, 2> { { &inputWrapper, &outputWrapper } }; }\r
 \r
-    StringArray getInputChannelNames() override\r
-    {\r
-        StringArray names;\r
-\r
-        for (auto* d : devices)\r
-            names.addArray (d->getInputChannelNames());\r
-\r
-        names.appendNumbersToDuplicates (false, true);\r
-        return names;\r
-    }\r
+    StringArray getOutputChannelNames() override        { return outputWrapper.getChannelNames(); }\r
+    StringArray getInputChannelNames()  override        { return inputWrapper .getChannelNames(); }\r
+    BigInteger getActiveOutputChannels() const override { return outputWrapper.getActiveChannels(); }\r
+    BigInteger getActiveInputChannels() const override  { return inputWrapper .getActiveChannels(); }\r
 \r
     Array<double> getAvailableSampleRates() override\r
     {\r
         Array<double> commonRates;\r
         bool first = true;\r
 \r
-        for (auto* d : devices)\r
+        for (auto& d : getDeviceWrappers())\r
         {\r
-            auto rates = d->device->getAvailableSampleRates();\r
+            auto rates = d->getAvailableSampleRates();\r
 \r
             if (first)\r
             {\r
@@ -1303,9 +1460,9 @@ public:
         Array<int> commonSizes;\r
         bool first = true;\r
 \r
-        for (auto* d : devices)\r
+        for (auto& d : getDeviceWrappers())\r
         {\r
-            auto sizes = d->device->getAvailableBufferSizes();\r
+            auto sizes = d->getAvailableBufferSizes();\r
 \r
             if (first)\r
             {\r
@@ -1330,8 +1487,8 @@ public:
     {\r
         int depth = 32;\r
 \r
-        for (auto* d : devices)\r
-            depth = jmin (depth, d->device->getCurrentBitDepth());\r
+        for (auto& d : getDeviceWrappers())\r
+            depth = jmin (depth, d->getCurrentBitDepth());\r
 \r
         return depth;\r
     }\r
@@ -1340,8 +1497,8 @@ public:
     {\r
         int size = 0;\r
 \r
-        for (auto* d : devices)\r
-            size = jmax (size, d->device->getDefaultBufferSize());\r
+        for (auto& d : getDeviceWrappers())\r
+            size = jmax (size, d->getDefaultBufferSize());\r
 \r
         return size;\r
     }\r
@@ -1366,29 +1523,18 @@ public:
             auto rates = getAvailableSampleRates();\r
 \r
             for (int i = 0; i < rates.size() && sampleRate < 44100.0; ++i)\r
-                sampleRate = rates.getUnchecked(i);\r
+                sampleRate = rates.getUnchecked (i);\r
         }\r
 \r
         currentSampleRate = sampleRate;\r
         currentBufferSize = bufferSize;\r
+        targetLatency = bufferSize;\r
 \r
-        const int fifoSize = bufferSize * 3 + 1;\r
-        int totalInputChanIndex = 0, totalOutputChanIndex = 0;\r
-        int chanIndex = 0;\r
-\r
-        for (auto* d : devices)\r
+        for (auto& d : getDeviceWrappers())\r
         {\r
-            BigInteger ins (inputChannels >> totalInputChanIndex);\r
-            BigInteger outs (outputChannels >> totalOutputChanIndex);\r
-\r
-            int numIns  = d->getInputChannelNames().size();\r
-            int numOuts = d->getOutputChannelNames().size();\r
-\r
-            totalInputChanIndex += numIns;\r
-            totalOutputChanIndex += numOuts;\r
-\r
-            String err = d->open (ins, outs, sampleRate, bufferSize,\r
-                                  chanIndex, fifoSize);\r
+            auto err = d->open (  d->isInput() ? inputChannels  : BigInteger(),\r
+                                ! d->isInput() ? outputChannels : BigInteger(),\r
+                                sampleRate, bufferSize);\r
 \r
             if (err.isNotEmpty())\r
             {\r
@@ -1397,15 +1543,13 @@ public:
                 return err;\r
             }\r
 \r
-            chanIndex += d->numInputChans + d->numOutputChans;\r
+            targetLatency += d->getLatencyInSamples();\r
         }\r
 \r
-        fifos.setSize (chanIndex, fifoSize);\r
-        fifoReadPointers  = fifos.getArrayOfReadPointers();\r
-        fifoWritePointers = fifos.getArrayOfWritePointers();\r
-        fifos.clear();\r
-        startThread (9);\r
-        threadInitialised.wait();\r
+        const auto numOuts = outputWrapper.getChannelNames().size();\r
+\r
+        fifo.setSize (numOuts, targetLatency + (bufferSize * 2));\r
+        scratchBuffer.setSize (numOuts, bufferSize);\r
 \r
         return {};\r
     }\r
@@ -1413,11 +1557,10 @@ public:
     void close() override\r
     {\r
         stop();\r
-        stopThread (10000);\r
-        fifos.clear();\r
+        fifo.clear();\r
         active = false;\r
 \r
-        for (auto* d : devices)\r
+        for (auto& d : getDeviceWrappers())\r
             d->close();\r
     }\r
 \r
@@ -1430,7 +1573,7 @@ public:
         auto newSampleRate = sampleRateRequested;\r
         auto newBufferSize = bufferSizeRequested;\r
 \r
-        for (auto* d : devices)\r
+        for (auto& d : getDeviceWrappers())\r
         {\r
             auto deviceSampleRate = d->getCurrentSampleRate();\r
 \r
@@ -1439,8 +1582,8 @@ public:
                 if (! getAvailableSampleRates().contains (deviceSampleRate))\r
                     return;\r
 \r
-                for (auto* d2 : devices)\r
-                    if (d2 != d)\r
+                for (auto& d2 : getDeviceWrappers())\r
+                    if (&d2 != &d)\r
                         d2->setCurrentSampleRate (deviceSampleRate);\r
 \r
                 newSampleRate = deviceSampleRate;\r
@@ -1448,7 +1591,7 @@ public:
             }\r
         }\r
 \r
-        for (auto* d : devices)\r
+        for (auto& d : getDeviceWrappers())\r
         {\r
             auto deviceBufferSize = d->getCurrentBufferSizeSamples();\r
 \r
@@ -1462,8 +1605,7 @@ public:
             }\r
         }\r
 \r
-        open (inputChannelsRequested, outputChannelsRequested,\r
-              newSampleRate, newBufferSize);\r
+        open (inputChannelsRequested, outputChannelsRequested, newSampleRate, newBufferSize);\r
 \r
         start (cb);\r
     }\r
@@ -1485,62 +1627,14 @@ public:
         startTimer (100);\r
     }\r
 \r
-    BigInteger getActiveOutputChannels() const override\r
-    {\r
-        BigInteger chans;\r
-        int start = 0;\r
-\r
-        for (auto* d : devices)\r
-        {\r
-            auto numChans = d->getOutputChannelNames().size();\r
-\r
-            if (numChans > 0)\r
-            {\r
-                chans |= (d->device->getActiveOutputChannels() << start);\r
-                start += numChans;\r
-            }\r
-        }\r
-\r
-        return chans;\r
-    }\r
-\r
-    BigInteger getActiveInputChannels() const override\r
-    {\r
-        BigInteger chans;\r
-        int start = 0;\r
-\r
-        for (auto* d : devices)\r
-        {\r
-            auto numChans = d->getInputChannelNames().size();\r
-\r
-            if (numChans > 0)\r
-            {\r
-                chans |= (d->device->getActiveInputChannels() << start);\r
-                start += numChans;\r
-            }\r
-        }\r
-\r
-        return chans;\r
-    }\r
-\r
     int getOutputLatencyInSamples() override\r
     {\r
-        int lat = 0;\r
-\r
-        for (auto* d : devices)\r
-            lat = jmax (lat, d->device->getOutputLatencyInSamples());\r
-\r
-        return lat + currentBufferSize * 2;\r
+        return targetLatency - getInputLatencyInSamples();\r
     }\r
 \r
     int getInputLatencyInSamples() override\r
     {\r
-        int lat = 0;\r
-\r
-        for (auto* d : devices)\r
-            lat = jmax (lat, d->device->getInputLatencyInSamples());\r
-\r
-        return lat + currentBufferSize * 2;\r
+        return inputWrapper.getLatencyInSamples();\r
     }\r
 \r
     void start (AudioIODeviceCallback* newCallback) override\r
@@ -1554,13 +1648,20 @@ public:
         if (shouldStart)\r
         {\r
             stop();\r
-            fifos.clear();\r
+            fifo.clear();\r
+            reset();\r
+\r
+            {\r
+                ScopedErrorForwarder forwarder (*this, newCallback);\r
 \r
-            for (auto* d : devices)\r
-                d->start();\r
+                for (auto& d : getDeviceWrappers())\r
+                    d->start (d);\r
 \r
-            if (newCallback != nullptr)\r
-                newCallback->audioDeviceAboutToStart (this);\r
+                if (! forwarder.encounteredError() && newCallback != nullptr)\r
+                    newCallback->audioDeviceAboutToStart (this);\r
+                else if (lastError.isEmpty())\r
+                    lastError = TRANS("Failed to initialise all requested devices.");\r
+            }\r
 \r
             const ScopedLock sl (callbackLock);\r
             previousCallback = callback = newCallback;\r
@@ -1574,7 +1675,14 @@ public:
         return lastError;\r
     }\r
 \r
+    int getXRunCount() const noexcept override\r
+    {\r
+        return xruns.load();\r
+    }\r
+\r
 private:\r
+    static constexpr auto invalidSampleTime = std::numeric_limits<std::uint64_t>::max();\r
+\r
     WeakReference<CoreAudioIODeviceType> owner;\r
     CriticalSection callbackLock;\r
     AudioIODeviceCallback* callback = nullptr;\r
@@ -1583,78 +1691,16 @@ private:
     int currentBufferSize = 0;\r
     bool active = false;\r
     String lastError;\r
-    AudioBuffer<float> fifos;\r
-    const float** fifoReadPointers = nullptr;\r
-    float** fifoWritePointers = nullptr;\r
-    WaitableEvent threadInitialised;\r
+    AudioSampleBuffer fifo, scratchBuffer;\r
     CriticalSection closeLock;\r
+    int targetLatency = 0;\r
+    std::atomic<int> xruns { -1 };\r
+    std::atomic<uint64_t> lastValidReadPosition { invalidSampleTime };\r
 \r
     BigInteger inputChannelsRequested, outputChannelsRequested;\r
     double sampleRateRequested = 44100;\r
     int bufferSizeRequested = 512;\r
 \r
-    void run() override\r
-    {\r
-        auto numSamples = currentBufferSize;\r
-\r
-        AudioBuffer<float> buffer (fifos.getNumChannels(), numSamples);\r
-        buffer.clear();\r
-\r
-        Array<const float*> inputChans;\r
-        Array<float*> outputChans;\r
-\r
-        for (auto* d : devices)\r
-        {\r
-            for (int j = 0; j < d->numInputChans; ++j)   inputChans.add  (buffer.getReadPointer  (d->inputIndex  + j));\r
-            for (int j = 0; j < d->numOutputChans; ++j)  outputChans.add (buffer.getWritePointer (d->outputIndex + j));\r
-        }\r
-\r
-        auto numInputChans  = inputChans.size();\r
-        auto numOutputChans = outputChans.size();\r
-\r
-        inputChans.add (nullptr);\r
-        outputChans.add (nullptr);\r
-\r
-        auto blockSizeMs = jmax (1, (int) (1000 * numSamples / currentSampleRate));\r
-\r
-        jassert (numInputChans + numOutputChans == buffer.getNumChannels());\r
-\r
-        threadInitialised.signal();\r
-\r
-        while (! threadShouldExit())\r
-        {\r
-            readInput (buffer, numSamples, blockSizeMs);\r
-\r
-            bool didCallback = true;\r
-\r
-            {\r
-                const ScopedLock sl (callbackLock);\r
-\r
-                if (callback != nullptr)\r
-                    callback->audioDeviceIOCallbackWithContext ((const float**) inputChans.getRawDataPointer(),\r
-                                                                numInputChans,\r
-                                                                outputChans.getRawDataPointer(),\r
-                                                                numOutputChans,\r
-                                                                numSamples,\r
-                                                                {}); // Can't predict when the next output callback will happen\r
-                else\r
-                    didCallback = false;\r
-            }\r
-\r
-            if (didCallback)\r
-            {\r
-                pushOutputData (buffer, numSamples, blockSizeMs);\r
-            }\r
-            else\r
-            {\r
-                for (int i = 0; i < numOutputChans; ++i)\r
-                    FloatVectorOperations::clear (outputChans[i], numSamples);\r
-\r
-                reset();\r
-            }\r
-        }\r
-    }\r
-\r
     void timerCallback() override\r
     {\r
         stopTimer();\r
@@ -1671,8 +1717,8 @@ private:
             std::swap (callback, lastCallback);\r
         }\r
 \r
-        for (auto* d : devices)\r
-            d->device->stopInternal();\r
+        for (auto& d : getDeviceWrappers())\r
+            d->stopInternal();\r
 \r
         if (lastCallback != nullptr)\r
         {\r
@@ -1685,90 +1731,152 @@ private:
 \r
     void reset()\r
     {\r
-        for (auto* d : devices)\r
+        xruns.store (0);\r
+        fifo.clear();\r
+        scratchBuffer.clear();\r
+\r
+        for (auto& d : getDeviceWrappers())\r
             d->reset();\r
     }\r
 \r
-    void underrun()\r
+    // AbstractFifo cannot be used here for two reasons:\r
+    // 1) We use absolute timestamps as the fifo's read/write positions. This not only makes the code\r
+    //    more readable (especially when checking for underruns/overflows) but also simplifies the\r
+    //    initial setup when actual latency is not known yet until both callbacks have fired.\r
+    // 2) AbstractFifo doesn't have the necessary mechanics to recover from underrun/overflow conditions\r
+    //    in a lock-free and data-race free way. It's great if you don't care (i.e. overwrite and/or\r
+    //    read stale data) or can abort the operation entirely, but this is not the case here. We\r
+    //    need bespoke underrun/overflow handling here which fits this use-case.\r
+    template <typename Callback>\r
+    void accessFifo (const uint64_t startPos, const int numChannels, const int numItems, Callback&& operateOnRange)\r
     {\r
+        const auto fifoSize = fifo.getNumSamples();\r
+        auto fifoPos = static_cast<int> (startPos % static_cast<std::uint64_t> (fifoSize));\r
+\r
+        for (int pos = 0; pos < numItems;)\r
+        {\r
+            const auto max = std::min (numItems - pos, fifoSize - fifoPos);\r
+\r
+            struct Args { int fifoPos, inputPos, nItems, channel; };\r
+\r
+            for (auto ch = 0; ch < numChannels; ++ch)\r
+                operateOnRange (Args { fifoPos, pos, max, ch });\r
+\r
+            fifoPos = (fifoPos + max) % fifoSize;\r
+            pos += max;\r
+        }\r
     }\r
 \r
-    void readInput (AudioBuffer<float>& buffer, const int numSamples, const int blockSizeMs)\r
+    void inputAudioCallback (const float* const* channels, int numChannels, int n, const AudioIODeviceCallbackContext& context) noexcept\r
     {\r
-        for (auto* d : devices)\r
-            d->done = (d->numInputChans == 0 || d->isWaitingForInput);\r
+        auto& writePos = inputWrapper.sampleTime;\r
 \r
-        float totalWaitTimeMs = blockSizeMs * 5.0f;\r
-        constexpr int numReadAttempts = 6;\r
-        auto sumPower2s = [] (int maxPower) { return (1 << (maxPower + 1)) - 1; };\r
-        float waitTime = totalWaitTimeMs / (float) sumPower2s (numReadAttempts - 2);\r
-\r
-        for (int numReadAttemptsRemaining = numReadAttempts;;)\r
         {\r
-            bool anySamplesRemaining = false;\r
+            ScopedLock lock (callbackLock);\r
 \r
-            for (auto* d : devices)\r
+            if (callback != nullptr)\r
             {\r
-                if (! d->done)\r
-                {\r
-                    if (d->isInputReady (numSamples))\r
-                    {\r
-                        d->readInput (buffer, numSamples);\r
-                        d->done = true;\r
-                    }\r
-                    else\r
-                    {\r
-                        anySamplesRemaining = true;\r
-                    }\r
-                }\r
+                const auto numActiveOutputChannels = outputWrapper.getActiveChannels().countNumberOfSetBits();\r
+                jassert (numActiveOutputChannels <= scratchBuffer.getNumChannels());\r
+\r
+                callback->audioDeviceIOCallbackWithContext (channels,\r
+                                                            numChannels,\r
+                                                            scratchBuffer.getArrayOfWritePointers(),\r
+                                                            numActiveOutputChannels,\r
+                                                            n,\r
+                                                            context);\r
+            }\r
+            else\r
+            {\r
+                scratchBuffer.clear();\r
             }\r
+        }\r
 \r
-            if (! anySamplesRemaining)\r
-                return;\r
+        auto currentWritePos = writePos.load();\r
+        const auto nextWritePos = currentWritePos + static_cast<std::uint64_t> (n);\r
 \r
-            if (--numReadAttemptsRemaining == 0)\r
-                break;\r
+        writePos.compare_exchange_strong (currentWritePos, nextWritePos);\r
+\r
+        if (currentWritePos == invalidSampleTime)\r
+            return;\r
+\r
+        const auto readPos = outputWrapper.sampleTime.load();\r
 \r
-            wait (jmax (1, roundToInt (waitTime)));\r
-            waitTime *= 2.0f;\r
+        // check for fifo overflow\r
+        if (readPos != invalidSampleTime)\r
+        {\r
+            // write will overlap previous read\r
+            if (readPos > currentWritePos || (currentWritePos + static_cast<std::uint64_t> (n) - readPos) > static_cast<std::uint64_t> (fifo.getNumSamples()))\r
+            {\r
+                xrun();\r
+                return;\r
+            }\r
         }\r
 \r
-        for (auto* d : devices)\r
-            if (! d->done)\r
-                for (int i = 0; i < d->numInputChans; ++i)\r
-                    buffer.clear (d->inputIndex + i, 0, numSamples);\r
+        accessFifo (currentWritePos, scratchBuffer.getNumChannels(), n, [&] (const auto& args)\r
+        {\r
+            FloatVectorOperations::copy (fifo.getWritePointer (args.channel, args.fifoPos),\r
+                                         scratchBuffer.getReadPointer (args.channel, args.inputPos),\r
+                                         args.nItems);\r
+        });\r
+\r
+        {\r
+            auto invalid = invalidSampleTime;\r
+            lastValidReadPosition.compare_exchange_strong (invalid, nextWritePos);\r
+        }\r
     }\r
 \r
-    void pushOutputData (AudioBuffer<float>& buffer, const int numSamples, const int blockSizeMs)\r
+    void outputAudioCallback (float* const* channels, int numChannels, int n) noexcept\r
     {\r
-        for (auto* d : devices)\r
-            d->done = (d->numOutputChans == 0);\r
+        auto& readPos = outputWrapper.sampleTime;\r
+        auto currentReadPos = readPos.load();\r
 \r
-        for (int tries = 5;;)\r
-        {\r
-            bool anyRemaining = false;\r
+        if (currentReadPos == invalidSampleTime)\r
+            return;\r
 \r
-            for (auto* d : devices)\r
+        const auto writePos = inputWrapper.sampleTime.load();\r
+\r
+        // check for fifo underrun\r
+        if (writePos != invalidSampleTime)\r
+        {\r
+            if ((currentReadPos + static_cast<std::uint64_t> (n)) > writePos)\r
             {\r
-                if (! d->done)\r
-                {\r
-                    if (d->isOutputReady (numSamples))\r
-                    {\r
-                        d->pushOutputData (buffer, numSamples);\r
-                        d->done = true;\r
-                    }\r
-                    else\r
-                    {\r
-                        anyRemaining = true;\r
-                    }\r
-                }\r
+                xrun();\r
+                return;\r
             }\r
+        }\r
 \r
-            if ((! anyRemaining) || --tries == 0)\r
-                return;\r
+        // If there was an xrun, we want to output zeros until we're sure that there's some valid\r
+        // input for us to read.\r
+        const auto longN = static_cast<uint64_t> (n);\r
+        const auto nextReadPos = currentReadPos + longN;\r
+        const auto validReadPos = lastValidReadPosition.load();\r
+        const auto sanitisedValidReadPos = validReadPos != invalidSampleTime ? validReadPos : nextReadPos;\r
+        const auto numZerosToWrite = sanitisedValidReadPos <= currentReadPos\r
+                                   ? 0\r
+                                   : jmin (longN, sanitisedValidReadPos - currentReadPos);\r
 \r
-            wait (blockSizeMs);\r
-        }\r
+        for (auto i = 0; i < numChannels; ++i)\r
+            std::fill (channels[i], channels[i] + numZerosToWrite, 0.0f);\r
+\r
+        accessFifo (currentReadPos + numZerosToWrite, numChannels, static_cast<int> (longN - numZerosToWrite), [&] (const auto& args)\r
+        {\r
+            FloatVectorOperations::copy (channels[args.channel] + args.inputPos + numZerosToWrite,\r
+                                         fifo.getReadPointer (args.channel, args.fifoPos),\r
+                                         args.nItems);\r
+        });\r
+\r
+        // use compare exchange here as we need to avoid the case\r
+        // where we overwrite readPos being equal to invalidSampleTime\r
+        readPos.compare_exchange_strong (currentReadPos, nextReadPos);\r
+    }\r
+\r
+    void xrun() noexcept\r
+    {\r
+        for (auto& d : getDeviceWrappers())\r
+            d->sampleTime.store (invalidSampleTime);\r
+\r
+        ++xruns;\r
     }\r
 \r
     void handleAudioDeviceAboutToStart (AudioIODevice* device)\r
@@ -1802,7 +1910,7 @@ private:
         currentSampleRate = newSampleRate;\r
         bool anySampleRateChanges = false;\r
 \r
-        for (auto* d : devices)\r
+        for (auto& d : getDeviceWrappers())\r
         {\r
             if (d->getCurrentSampleRate() != currentSampleRate)\r
             {\r
@@ -1822,215 +1930,156 @@ private:
     void handleAudioDeviceError (const String& errorMessage)   { shutdown (errorMessage.isNotEmpty() ? errorMessage : String ("unknown")); }\r
 \r
     //==============================================================================\r
-    struct DeviceWrapper  : private AudioIODeviceCallback\r
+    struct DeviceWrapper  : public AudioIODeviceCallback\r
     {\r
-        DeviceWrapper (AudioIODeviceCombiner& cd, std::unique_ptr<CoreAudioIODevice> d, bool useIns, bool useOuts)\r
-            : owner (cd), device (std::move (d)),\r
-              useInputs (useIns), useOutputs (useOuts)\r
+        DeviceWrapper (AudioIODeviceCombiner& cd, std::unique_ptr<CoreAudioIODevice> d, bool shouldBeInput)\r
+            : owner (cd),\r
+              device (std::move (d)),\r
+              input (shouldBeInput)\r
         {\r
             device->setAsyncRestarter (&owner);\r
         }\r
 \r
         ~DeviceWrapper() override\r
-        {\r
-            close();\r
-        }\r
-\r
-        String open (const BigInteger& inputChannels, const BigInteger& outputChannels,\r
-                     double sampleRate, int bufferSize, int channelIndex, int fifoSize)\r
-        {\r
-            inputFifo.setTotalSize (fifoSize);\r
-            outputFifo.setTotalSize (fifoSize);\r
-            inputFifo.reset();\r
-            outputFifo.reset();\r
-\r
-            auto err = device->open (useInputs  ? inputChannels  : BigInteger(),\r
-                                     useOutputs ? outputChannels : BigInteger(),\r
-                                     sampleRate, bufferSize);\r
-\r
-            numInputChans  = useInputs  ? device->getActiveInputChannels().countNumberOfSetBits()  : 0;\r
-            numOutputChans = useOutputs ? device->getActiveOutputChannels().countNumberOfSetBits() : 0;\r
-\r
-            isWaitingForInput = numInputChans > 0;\r
-\r
-            inputIndex = channelIndex;\r
-            outputIndex = channelIndex + numInputChans;\r
-\r
-            return err;\r
-        }\r
-\r
-        void close()\r
         {\r
             device->close();\r
         }\r
 \r
-        void start()\r
+        void reset()\r
         {\r
-            reset();\r
-            device->start (this);\r
+            sampleTime.store (invalidSampleTime);\r
         }\r
 \r
-        void reset()\r
+        void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
+                                               int numInputChannels,\r
+                                               float* const* outputChannelData,\r
+                                               int numOutputChannels,\r
+                                               int numSamples,\r
+                                               const AudioIODeviceCallbackContext& context) override\r
         {\r
-            inputFifo.reset();\r
-            outputFifo.reset();\r
-        }\r
+            if (std::exchange (device->hadDiscontinuity, false))\r
+                owner.xrun();\r
 \r
-        StringArray getOutputChannelNames() const  { return useOutputs ? device->getOutputChannelNames() : StringArray(); }\r
-        StringArray getInputChannelNames()  const  { return useInputs  ? device->getInputChannelNames()  : StringArray(); }\r
+            updateSampleTimeFromContext (context);\r
 \r
-        bool isInputReady (int numSamples) const noexcept\r
-        {\r
-            return numInputChans == 0 || inputFifo.getNumReady() >= numSamples;\r
+            if (input)\r
+                owner.inputAudioCallback (inputChannelData, numInputChannels, numSamples, context);\r
+            else\r
+                owner.outputAudioCallback (outputChannelData, numOutputChannels, numSamples);\r
         }\r
 \r
-        void readInput (AudioBuffer<float>& destBuffer, int numSamples)\r
+        void audioDeviceAboutToStart (AudioIODevice* d)        override { owner.handleAudioDeviceAboutToStart (d); }\r
+        void audioDeviceStopped()                              override { owner.handleAudioDeviceStopped(); }\r
+        void audioDeviceError (const String& errorMessage)     override { owner.handleAudioDeviceError (errorMessage); }\r
+\r
+        bool setCurrentSampleRate (double newSampleRate)                { return device->setCurrentSampleRate (newSampleRate); }\r
+        StringArray getChannelNames()                             const { return input ? device->getInputChannelNames()     : device->getOutputChannelNames(); }\r
+        BigInteger getActiveChannels()                            const { return input ? device->getActiveInputChannels()   : device->getActiveOutputChannels(); }\r
+        int getLatencyInSamples()                                 const { return input ? device->getInputLatencyInSamples() : device->getOutputLatencyInSamples(); }\r
+        int getIndexOfDevice (bool asInput)                       const { return device->getIndexOfDevice (asInput); }\r
+        double getCurrentSampleRate()                             const { return device->getCurrentSampleRate(); }\r
+        int getCurrentBufferSizeSamples()                         const { return device->getCurrentBufferSizeSamples(); }\r
+        Array<double> getAvailableSampleRates()                   const { return device->getAvailableSampleRates(); }\r
+        Array<int> getAvailableBufferSizes()                      const { return device->getAvailableBufferSizes(); }\r
+        int getCurrentBitDepth()                                  const { return device->getCurrentBitDepth(); }\r
+        int getDefaultBufferSize()                                const { return device->getDefaultBufferSize(); }\r
+        void start (AudioIODeviceCallback* callbackToNotify)      const { return device->start (callbackToNotify); }\r
+        AudioIODeviceCallback* stopInternal()                     const { return device->stopInternal(); }\r
+        void close()                                              const { return device->close(); }\r
+\r
+        String open (const BigInteger& inputChannels, const BigInteger& outputChannels, double sampleRate, int bufferSizeSamples) const\r
         {\r
-            if (numInputChans == 0)\r
-                return;\r
-\r
-            int start1, size1, start2, size2;\r
-            inputFifo.prepareToRead (numSamples, start1, size1, start2, size2);\r
-\r
-            for (int i = 0; i < numInputChans; ++i)\r
-            {\r
-                auto index = inputIndex + i;\r
-                auto dest = destBuffer.getWritePointer (index);\r
-                auto src = owner.fifoReadPointers[index];\r
-\r
-                if (size1 > 0)  FloatVectorOperations::copy (dest,         src + start1, size1);\r
-                if (size2 > 0)  FloatVectorOperations::copy (dest + size1, src + start2, size2);\r
-            }\r
-\r
-            inputFifo.finishedRead (size1 + size2);\r
+            return device->open (inputChannels, outputChannels, sampleRate, bufferSizeSamples);\r
         }\r
 \r
-        bool isOutputReady (int numSamples) const noexcept\r
+        std::uint64_t nsToSampleTime (std::uint64_t ns) const noexcept\r
         {\r
-            return numOutputChans == 0 || outputFifo.getFreeSpace() >= numSamples;\r
+            return static_cast<std::uint64_t> (std::round (static_cast<double> (ns) * device->getCurrentSampleRate() * 1e-9));\r
         }\r
 \r
-        void pushOutputData (AudioBuffer<float>& srcBuffer, int numSamples)\r
+        void updateSampleTimeFromContext (const AudioIODeviceCallbackContext& context) noexcept\r
         {\r
-            if (numOutputChans == 0)\r
-                return;\r
-\r
-            int start1, size1, start2, size2;\r
-            outputFifo.prepareToWrite (numSamples, start1, size1, start2, size2);\r
+            auto callbackSampleTime = context.hostTimeNs != nullptr ? nsToSampleTime (*context.hostTimeNs) : 0;\r
 \r
-            for (int i = 0; i < numOutputChans; ++i)\r
-            {\r
-                auto index = outputIndex + i;\r
-                auto dest = owner.fifoWritePointers[index];\r
-                auto src = srcBuffer.getReadPointer (index);\r
+            if (input)\r
+                callbackSampleTime += static_cast<std::uint64_t> (owner.targetLatency);\r
 \r
-                if (size1 > 0)  FloatVectorOperations::copy (dest + start1, src,         size1);\r
-                if (size2 > 0)  FloatVectorOperations::copy (dest + start2, src + size1, size2);\r
-            }\r
+            auto copy = invalidSampleTime;\r
 \r
-            outputFifo.finishedWrite (size1 + size2);\r
+            if (sampleTime.compare_exchange_strong (copy, callbackSampleTime) && (! input))\r
+                owner.lastValidReadPosition = invalidSampleTime;\r
         }\r
 \r
-        void audioDeviceIOCallbackWithContext (const float** inputChannelData,\r
-                                               int numInputChannels,\r
-                                               float** outputChannelData,\r
-                                               int numOutputChannels,\r
-                                               int numSamples,\r
-                                               const AudioIODeviceCallbackContext&) override\r
-        {\r
-            if (numInputChannels > 0)\r
-            {\r
-                isWaitingForInput = false;\r
-\r
-                int start1, size1, start2, size2;\r
-                inputFifo.prepareToWrite (numSamples, start1, size1, start2, size2);\r
-\r
-                if (size1 + size2 < numSamples)\r
-                {\r
-                    inputFifo.reset();\r
-                    inputFifo.prepareToWrite (numSamples, start1, size1, start2, size2);\r
-                }\r
-\r
-                for (int i = 0; i < numInputChannels; ++i)\r
-                {\r
-                    auto dest = owner.fifoWritePointers[inputIndex + i];\r
-                    auto src = inputChannelData[i];\r
+        bool isInput() const { return input; }\r
 \r
-                    if (size1 > 0)  FloatVectorOperations::copy (dest + start1, src,         size1);\r
-                    if (size2 > 0)  FloatVectorOperations::copy (dest + start2, src + size1, size2);\r
-                }\r
+        std::atomic<std::uint64_t> sampleTime { invalidSampleTime };\r
 \r
-                auto totalSize = size1 + size2;\r
-                inputFifo.finishedWrite (totalSize);\r
+    private:\r
 \r
-                if (numSamples > totalSize)\r
-                {\r
-                    auto samplesRemaining = numSamples - totalSize;\r
+        //==============================================================================\r
+        AudioIODeviceCombiner& owner;\r
+        std::unique_ptr<CoreAudioIODevice> device;\r
+        const bool input;\r
 \r
-                    for (int i = 0; i < numInputChans; ++i)\r
-                        FloatVectorOperations::clear (owner.fifoWritePointers[inputIndex + i] + totalSize, samplesRemaining);\r
+        //==============================================================================\r
+        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DeviceWrapper)\r
+    };\r
 \r
-                    owner.underrun();\r
-                }\r
-            }\r
+    /* If the current AudioIODeviceCombiner::callback is nullptr, it sets itself as the callback\r
+       and forwards error related callbacks to the provided callback\r
+    */\r
+    class ScopedErrorForwarder  : public AudioIODeviceCallback\r
+    {\r
+    public:\r
+        ScopedErrorForwarder (AudioIODeviceCombiner& ownerIn, AudioIODeviceCallback* cb)\r
+            : owner (ownerIn),\r
+              target (cb)\r
+        {\r
+            const ScopedLock sl (owner.callbackLock);\r
 \r
-            if (numOutputChannels > 0)\r
-            {\r
-                int start1, size1, start2, size2;\r
-                outputFifo.prepareToRead (numSamples, start1, size1, start2, size2);\r
+            if (owner.callback == nullptr)\r
+                owner.callback = this;\r
+        }\r
 \r
-                if (size1 + size2 < numSamples)\r
-                {\r
-                    Thread::sleep (1);\r
-                    outputFifo.prepareToRead (numSamples, start1, size1, start2, size2);\r
-                }\r
+        ~ScopedErrorForwarder() override\r
+        {\r
+            const ScopedLock sl (owner.callbackLock);\r
 \r
-                for (int i = 0; i < numOutputChannels; ++i)\r
-                {\r
-                    auto dest = outputChannelData[i];\r
-                    auto src = owner.fifoReadPointers[outputIndex + i];\r
+            if (owner.callback == this)\r
+                owner.callback = nullptr;\r
+        }\r
 \r
-                    if (size1 > 0)  FloatVectorOperations::copy (dest,         src + start1, size1);\r
-                    if (size2 > 0)  FloatVectorOperations::copy (dest + size1, src + start2, size2);\r
-                }\r
+        // We only want to be notified about error conditions when the owner's callback is nullptr.\r
+        // This class shouldn't be relied on for forwarding this call.\r
+        void audioDeviceAboutToStart (AudioIODevice*) override {}\r
 \r
-                auto totalSize = size1 + size2;\r
-                outputFifo.finishedRead (totalSize);\r
+        void audioDeviceStopped() override\r
+        {\r
+            if (target != nullptr)\r
+                target->audioDeviceStopped();\r
 \r
-                if (numSamples > totalSize)\r
-                {\r
-                    auto samplesRemaining = numSamples - totalSize;\r
+            error = true;\r
+        }\r
 \r
-                    for (int i = 0; i < numOutputChannels; ++i)\r
-                        FloatVectorOperations::clear (outputChannelData[i] + totalSize, samplesRemaining);\r
+        void audioDeviceError (const String& errorMessage) override\r
+        {\r
+            owner.lastError = errorMessage;\r
 \r
-                    owner.underrun();\r
-                }\r
-            }\r
+            if (target != nullptr)\r
+                target->audioDeviceError (errorMessage);\r
 \r
-            owner.notify();\r
+            error = true;\r
         }\r
 \r
-        double getCurrentSampleRate()                        { return device->getCurrentSampleRate(); }\r
-        bool   setCurrentSampleRate (double newSampleRate)   { return device->setCurrentSampleRate (newSampleRate); }\r
-        int  getCurrentBufferSizeSamples()                   { return device->getCurrentBufferSizeSamples(); }\r
-\r
-        void audioDeviceAboutToStart (AudioIODevice* d) override      { owner.handleAudioDeviceAboutToStart (d); }\r
-        void audioDeviceStopped() override                            { owner.handleAudioDeviceStopped(); }\r
-        void audioDeviceError (const String& errorMessage) override   { owner.handleAudioDeviceError (errorMessage); }\r
+        bool encounteredError() const { return error; }\r
 \r
+    private:\r
         AudioIODeviceCombiner& owner;\r
-        std::unique_ptr<CoreAudioIODevice> device;\r
-        int inputIndex = 0, numInputChans = 0, outputIndex = 0, numOutputChans = 0;\r
-        bool useInputs = false, useOutputs = false;\r
-        std::atomic<bool> isWaitingForInput { false };\r
-        AbstractFifo inputFifo { 32 }, outputFifo { 32 };\r
-        bool done = false;\r
-\r
-        JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (DeviceWrapper)\r
+        AudioIODeviceCallback* target;\r
+        bool error = false;\r
     };\r
 \r
-    OwnedArray<DeviceWrapper> devices;\r
+    DeviceWrapper inputWrapper, outputWrapper;\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioIODeviceCombiner)\r
 };\r
@@ -2073,45 +2122,30 @@ public:
         inputIds.clear();\r
         outputIds.clear();\r
 \r
-        UInt32 size;\r
-\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mSelector = kAudioHardwarePropertyDevices;\r
-        pa.mScope = kAudioObjectPropertyScopeWildcard;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
+        auto audioDevices = audioObjectGetProperties<AudioDeviceID> (kAudioObjectSystemObject, { kAudioHardwarePropertyDevices,\r
+                                                                                                 kAudioObjectPropertyScopeWildcard,\r
+                                                                                                 juceAudioObjectPropertyElementMain });\r
 \r
-        if (AudioObjectGetPropertyDataSize (kAudioObjectSystemObject, &pa, 0, nullptr, &size) == noErr)\r
+        for (const auto audioDevice : audioDevices)\r
         {\r
-            HeapBlock<AudioDeviceID> devs;\r
-            devs.calloc (size, 1);\r
-\r
-            if (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, nullptr, &size, devs) == noErr)\r
+            if (const auto optionalName = audioObjectGetProperty<CFStringRef> (audioDevice, { kAudioDevicePropertyDeviceNameCFString,\r
+                                                                                              kAudioObjectPropertyScopeWildcard,\r
+                                                                                              juceAudioObjectPropertyElementMain }))\r
             {\r
-                auto num = (int) size / (int) sizeof (AudioDeviceID);\r
-\r
-                for (int i = 0; i < num; ++i)\r
+                if (const CFUniquePtr<CFStringRef> name { *optionalName })\r
                 {\r
-                    char name[1024];\r
-                    size = sizeof (name);\r
-                    pa.mSelector = kAudioDevicePropertyDeviceName;\r
+                    const auto nameString = String::fromCFString (name.get());\r
+\r
+                    if (const auto numIns  = getNumChannels (audioDevice, true); numIns > 0)\r
+                    {\r
+                        inputDeviceNames.add (nameString);\r
+                        inputIds.add (audioDevice);\r
+                    }\r
 \r
-                    if (AudioObjectGetPropertyData (devs[i], &pa, 0, nullptr, &size, name) == noErr)\r
+                    if (const auto numOuts = getNumChannels (audioDevice, false); numOuts > 0)\r
                     {\r
-                        auto nameString = String::fromUTF8 (name, (int) strlen (name));\r
-                        auto numIns  = getNumChannels (devs[i], true);\r
-                        auto numOuts = getNumChannels (devs[i], false);\r
-\r
-                        if (numIns > 0)\r
-                        {\r
-                            inputDeviceNames.add (nameString);\r
-                            inputIds.add (devs[i]);\r
-                        }\r
-\r
-                        if (numOuts > 0)\r
-                        {\r
-                            outputDeviceNames.add (nameString);\r
-                            outputIds.add (devs[i]);\r
-                        }\r
+                        outputDeviceNames.add (nameString);\r
+                        outputIds.add (audioDevice);\r
                     }\r
                 }\r
             }\r
@@ -2133,32 +2167,23 @@ public:
     {\r
         jassert (hasScanned); // need to call scanForDevices() before doing this\r
 \r
-        AudioDeviceID deviceID;\r
-        UInt32 size = sizeof (deviceID);\r
-\r
         // if they're asking for any input channels at all, use the default input, so we\r
         // get the built-in mic rather than the built-in output with no inputs..\r
 \r
         AudioObjectPropertyAddress pa;\r
-        pa.mSelector = forInput ? kAudioHardwarePropertyDefaultInputDevice\r
-                                : kAudioHardwarePropertyDefaultOutputDevice;\r
+        auto selector = forInput ? kAudioHardwarePropertyDefaultInputDevice\r
+                                 : kAudioHardwarePropertyDefaultOutputDevice;\r
         pa.mScope    = kAudioObjectPropertyScopeWildcard;\r
         pa.mElement  = juceAudioObjectPropertyElementMain;\r
 \r
-        if (AudioObjectGetPropertyData (kAudioObjectSystemObject, &pa, 0, nullptr, &size, &deviceID) == noErr)\r
+        if (auto deviceID = audioObjectGetProperty<AudioDeviceID> (kAudioObjectSystemObject, { selector,\r
+                                                                                               kAudioObjectPropertyScopeWildcard,\r
+                                                                                               juceAudioObjectPropertyElementMain }))\r
         {\r
-            if (forInput)\r
-            {\r
-                for (int i = inputIds.size(); --i >= 0;)\r
-                    if (inputIds[i] == deviceID)\r
-                        return i;\r
-            }\r
-            else\r
-            {\r
-                for (int i = outputIds.size(); --i >= 0;)\r
-                    if (outputIds[i] == deviceID)\r
-                        return i;\r
-            }\r
+            auto& ids = forInput ? inputIds : outputIds;\r
+\r
+            if (auto it = std::find (ids.begin(), ids.end(), deviceID); it != ids.end())\r
+                return static_cast<int> (std::distance (ids.begin(), it));\r
         }\r
 \r
         return 0;\r
@@ -2169,19 +2194,12 @@ public:
         jassert (hasScanned); // need to call scanForDevices() before doing this\r
 \r
         if (auto* d = dynamic_cast<CoreAudioIODevice*> (device))\r
-            return asInput ? d->inputIndex\r
-                           : d->outputIndex;\r
+            return d->getIndexOfDevice (asInput);\r
 \r
         if (auto* d = dynamic_cast<AudioIODeviceCombiner*> (device))\r
-        {\r
-            for (auto* dev : d->getDevices())\r
-            {\r
-                auto index = getIndexOfDevice (dev, asInput);\r
-\r
-                if (index >= 0)\r
+            for (auto* dev : d->getDeviceWrappers())\r
+                if (const auto index = dev->getIndexOfDevice (asInput); index >= 0)\r
                     return index;\r
-            }\r
-        }\r
 \r
         return -1;\r
     }\r
@@ -2217,9 +2235,7 @@ public:
         if (in  == nullptr)  return out.release();\r
         if (out == nullptr)  return in.release();\r
 \r
-        auto combo = std::make_unique<AudioIODeviceCombiner> (combinedName, this);\r
-        combo->addDevice (std::move (in),  true, false);\r
-        combo->addDevice (std::move (out), false, true);\r
+        auto combo = std::make_unique<AudioIODeviceCombiner> (combinedName, this, std::move (in), std::move (out));\r
         return combo.release();\r
     }\r
 \r
@@ -2244,25 +2260,15 @@ private:
     static int getNumChannels (AudioDeviceID deviceID, bool input)\r
     {\r
         int total = 0;\r
-        UInt32 size;\r
-\r
-        AudioObjectPropertyAddress pa;\r
-        pa.mSelector = kAudioDevicePropertyStreamConfiguration;\r
-        pa.mScope = input ? kAudioDevicePropertyScopeInput : kAudioDevicePropertyScopeOutput;\r
-        pa.mElement = juceAudioObjectPropertyElementMain;\r
 \r
-        if (AudioObjectGetPropertyDataSize (deviceID, &pa, 0, nullptr, &size) == noErr)\r
+        if (auto bufList = audioObjectGetProperty<AudioBufferList> (deviceID, { kAudioDevicePropertyStreamConfiguration,\r
+                                                                                CoreAudioInternal::getScope (input),\r
+                                                                                juceAudioObjectPropertyElementMain }))\r
         {\r
-            HeapBlock<AudioBufferList> bufList;\r
-            bufList.calloc (size, 1);\r
+            auto numStreams = (int) bufList->mNumberBuffers;\r
 \r
-            if (AudioObjectGetPropertyData (deviceID, &pa, 0, nullptr, &size, bufList) == noErr)\r
-            {\r
-                auto numStreams = (int) bufList->mNumberBuffers;\r
-\r
-                for (int i = 0; i < numStreams; ++i)\r
-                    total += bufList->mBuffers[i].mNumberChannels;\r
-            }\r
+            for (int i = 0; i < numStreams; ++i)\r
+                total += bufList->mBuffers[i].mNumberChannels;\r
         }\r
 \r
         return total;\r
index 4f6d8b81035195d725e0fa703491324acc622c28..fd61986e7a97d7ce4f2216c8dfb5d1856ebb4e3a 100644 (file)
@@ -29,7 +29,7 @@ namespace juce
 \r
 namespace CoreMidiHelpers\r
 {\r
-    static bool checkError (OSStatus err, int lineNum)\r
+    static bool checkError (OSStatus err, [[maybe_unused]] int lineNum)\r
     {\r
         if (err == noErr)\r
             return true;\r
@@ -38,7 +38,6 @@ namespace CoreMidiHelpers
         Logger::writeToLog ("CoreMIDI error: " + String (lineNum) + " - " + String::toHexString ((int) err));\r
        #endif\r
 \r
-        ignoreUnused (lineNum);\r
         return false;\r
     }\r
 \r
@@ -661,11 +660,11 @@ namespace CoreMidiHelpers
             : u32InputHandler (std::make_unique<ump::U32ToBytestreamHandler> (input, callback))\r
         {}\r
 \r
-        void dispatch (const MIDIEventList& list, double time) const\r
+        void dispatch (const MIDIEventList* list, double time) const\r
         {\r
-            auto* packet = &list.packet[0];\r
+            auto* packet = list->packet;\r
 \r
-            for (uint32_t i = 0; i < list.numPackets; ++i)\r
+            for (uint32_t i = 0; i < list->numPackets; ++i)\r
             {\r
                 static_assert (sizeof (uint32_t) == sizeof (UInt32)\r
                                && alignof (uint32_t) == alignof (UInt32),\r
@@ -695,11 +694,11 @@ namespace CoreMidiHelpers
             : bytestreamInputHandler (std::make_unique<ump::BytestreamToBytestreamHandler> (input, callback))\r
         {}\r
 \r
-        void dispatch (const MIDIPacketList& list, double time) const\r
+        void dispatch (const MIDIPacketList* list, double time) const\r
         {\r
-            auto* packet = &list.packet[0];\r
+            auto* packet = list->packet;\r
 \r
-            for (unsigned int i = 0; i < list.numPackets; ++i)\r
+            for (unsigned int i = 0; i < list->numPackets; ++i)\r
             {\r
                 auto len = readUnaligned<decltype (packet->length)> (&(packet->length));\r
                 bytestreamInputHandler->pushMidiData (packet->data, len, time);\r
@@ -725,12 +724,12 @@ namespace CoreMidiHelpers
             : newReceiver (input, callback), oldReceiver (input, callback)\r
         {}\r
 \r
-        void dispatch (const MIDIEventList& list, double time) const\r
+        void dispatch (const MIDIEventList* list, double time) const\r
         {\r
             newReceiver.dispatch (list, time);\r
         }\r
 \r
-        void dispatch (const MIDIPacketList& list, double time) const\r
+        void dispatch (const MIDIPacketList* list, double time) const\r
         {\r
             oldReceiver.dispatch (list, time);\r
         }\r
@@ -768,7 +767,7 @@ namespace CoreMidiHelpers
         }\r
 \r
         template <typename EventList>\r
-        void handlePackets (const EventList& list)\r
+        void handlePackets (const EventList* list)\r
         {\r
             const auto time = Time::getMillisecondCounterHiRes() * 0.001;\r
 \r
@@ -885,7 +884,7 @@ namespace CoreMidiHelpers
 \r
         static void newMidiInputProc (const MIDIEventList* list, void* readProcRefCon, void*)\r
         {\r
-            static_cast<MidiPortAndCallback*> (readProcRefCon)->handlePackets (*list);\r
+            static_cast<MidiPortAndCallback*> (readProcRefCon)->handlePackets (list);\r
         }\r
     };\r
    #endif\r
@@ -928,7 +927,7 @@ namespace CoreMidiHelpers
     private:\r
         static void oldMidiInputProc (const MIDIPacketList* list, void* readProcRefCon, void*)\r
         {\r
-            static_cast<MidiPortAndCallback*> (readProcRefCon)->handlePackets (*list);\r
+            static_cast<MidiPortAndCallback*> (readProcRefCon)->handlePackets (list);\r
         }\r
     };\r
    #endif\r
index 529c8b6f29a939df88d409f2090ffa2fbc087a3a..eb46baf7bc8ec59dad88ff016364fbd48d6eb628 100644 (file)
@@ -330,7 +330,7 @@ public:
         openDevice();\r
     }\r
 \r
-    ~ASIOAudioIODevice()\r
+    ~ASIOAudioIODevice() override\r
     {\r
         for (int i = 0; i < maxNumASIODevices; ++i)\r
             if (currentASIODev[i] == this)\r
@@ -1157,7 +1157,7 @@ private:
 \r
         // Get error message if init() failed, or if it's a buggy Denon driver,\r
         // which returns true from init() even when it fails.\r
-        if ((! initOk) || getName().containsIgnoreCase ("denon dj"))\r
+        if ((! initOk) || getName().containsIgnoreCase ("denon dj asio"))\r
             driverError = getLastDriverError();\r
 \r
         if ((! initOk) && driverError.isEmpty())\r
@@ -1326,7 +1326,7 @@ private:
                     inputFormat[i].convertToFloat (infos[i].buffers[bufferIndex], inBuffers[i], samps);\r
                 }\r
 \r
-                currentCallback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inBuffers.getData()),\r
+                currentCallback->audioDeviceIOCallbackWithContext (inBuffers.getData(),\r
                                                                    numActiveInputChans,\r
                                                                    outBuffers,\r
                                                                    numActiveOutputChans,\r
index b0e5dcd1b5d52872f3e974216cb5d0452f71a78d..017bee61e893f8115a9e459ac24e857d3240fb8f 100644 (file)
@@ -251,8 +251,8 @@ public:
         if (pOutputBuffer != nullptr)\r
         {\r
             JUCE_DS_LOG ("closing output: " + name);\r
-            HRESULT hr = pOutputBuffer->Stop();\r
-            JUCE_DS_LOG_ERROR (hr); ignoreUnused (hr);\r
+            [[maybe_unused]] HRESULT hr = pOutputBuffer->Stop();\r
+            JUCE_DS_LOG_ERROR (hr);\r
 \r
             pOutputBuffer->Release();\r
             pOutputBuffer = nullptr;\r
@@ -555,8 +555,8 @@ public:
         if (pInputBuffer != nullptr)\r
         {\r
             JUCE_DS_LOG ("closing input: " + name);\r
-            HRESULT hr = pInputBuffer->Stop();\r
-            JUCE_DS_LOG_ERROR (hr); ignoreUnused (hr);\r
+            [[maybe_unused]] HRESULT hr = pInputBuffer->Stop();\r
+            JUCE_DS_LOG_ERROR (hr);\r
 \r
             pInputBuffer->Release();\r
             pInputBuffer = nullptr;\r
@@ -1196,7 +1196,7 @@ String DSoundAudioIODevice::openDevice (const BigInteger& inputChannels,
         for (int i = 0; i < inChans.size(); ++i)\r
             inChans.getUnchecked(i)->synchronisePosition();\r
 \r
-        startThread (9);\r
+        startThread (Priority::highest);\r
         sleep (10);\r
 \r
         notify();\r
index 803f5b34f67876011948c175a7dd561f96c305be..c2b13f70983ae955fd7ab17308a5640bfde54482 100644 (file)
 namespace juce\r
 {\r
 \r
+template <typename T>\r
+class CheckedReference\r
+{\r
+public:\r
+    template <typename Ptr>\r
+    friend auto createCheckedReference (Ptr*);\r
+\r
+    void clear()\r
+    {\r
+        std::lock_guard lock { mutex };\r
+        ptr = nullptr;\r
+    }\r
+\r
+    template <typename Callback>\r
+    void access (Callback&& callback)\r
+    {\r
+        std::lock_guard lock { mutex };\r
+        callback (ptr);\r
+    }\r
+\r
+private:\r
+    explicit CheckedReference (T* ptrIn)  : ptr (ptrIn) {}\r
+\r
+    T* ptr;\r
+    std::mutex mutex;\r
+};\r
+\r
+template <typename Ptr>\r
+auto createCheckedReference (Ptr* ptrIn)\r
+{\r
+    return std::shared_ptr<CheckedReference<Ptr>> { new CheckedReference<Ptr> (ptrIn) };\r
+}\r
+\r
 class MidiInput::Pimpl\r
 {\r
 public:\r
@@ -1417,59 +1450,56 @@ private:
     };\r
 \r
     //==============================================================================\r
-    template <typename COMFactoryType, typename COMInterfaceType, typename COMType>\r
-    struct OpenMidiPortThread  : public Thread\r
+    template <typename COMType, typename COMFactoryType, typename COMInterfaceType>\r
+    static void openMidiPortThread (String threadName,\r
+                                    String midiDeviceID,\r
+                                    ComSmartPtr<COMFactoryType>& comFactory,\r
+                                    ComSmartPtr<COMInterfaceType>& comPort)\r
     {\r
-        OpenMidiPortThread (String threadName, String midiDeviceID,\r
-                            ComSmartPtr<COMFactoryType>& comFactory,\r
-                            ComSmartPtr<COMInterfaceType>& comPort)\r
-            : Thread (threadName),\r
-              deviceID (midiDeviceID),\r
-              factory (comFactory),\r
-              port (comPort)\r
-        {\r
-        }\r
-\r
-        ~OpenMidiPortThread()\r
+        std::thread { [&]\r
         {\r
-            stopThread (2000);\r
-        }\r
+            Thread::setCurrentThreadName (threadName);\r
 \r
-        void run() override\r
-        {\r
-            WinRTWrapper::ScopedHString hDeviceId (deviceID);\r
+            const WinRTWrapper::ScopedHString hDeviceId { midiDeviceID };\r
             ComSmartPtr<IAsyncOperation<COMType*>> asyncOp;\r
-            auto hr = factory->FromIdAsync (hDeviceId.get(), asyncOp.resetAndGetPointerAddress());\r
+            const auto hr = comFactory->FromIdAsync (hDeviceId.get(), asyncOp.resetAndGetPointerAddress());\r
 \r
             if (FAILED (hr))\r
                 return;\r
 \r
-            hr = asyncOp->put_Completed (Callback<IAsyncOperationCompletedHandler<COMType*>> (\r
-                [this] (IAsyncOperation<COMType*>* asyncOpPtr, AsyncStatus)\r
-                {\r
-                    if (asyncOpPtr == nullptr)\r
-                        return E_ABORT;\r
+            std::promise<ComSmartPtr<COMInterfaceType>> promise;\r
+            auto future = promise.get_future();\r
 \r
-                    auto hr = asyncOpPtr->GetResults (port.resetAndGetPointerAddress());\r
+            auto callback = [p = std::move (promise)] (IAsyncOperation<COMType*>* asyncOpPtr, AsyncStatus) mutable\r
+            {\r
+               if (asyncOpPtr == nullptr)\r
+               {\r
+                   p.set_value (nullptr);\r
+                   return E_ABORT;\r
+               }\r
 \r
-                    if (FAILED (hr))\r
-                        return hr;\r
+               ComSmartPtr<COMInterfaceType> result;\r
+               const auto hr = asyncOpPtr->GetResults (result.resetAndGetPointerAddress());\r
 \r
-                    portOpened.signal();\r
-                    return S_OK;\r
-                }\r
-            ).Get());\r
+               if (FAILED (hr))\r
+               {\r
+                   p.set_value (nullptr);\r
+                   return hr;\r
+               }\r
 \r
-            // We need to use a timeout here, rather than waiting indefinitely, as the\r
-            // WinRT API can occasionally hang!\r
-            portOpened.wait (2000);\r
-        }\r
+               p.set_value (std::move (result));\r
+               return S_OK;\r
+           };\r
 \r
-        const String deviceID;\r
-        ComSmartPtr<COMFactoryType>& factory;\r
-        ComSmartPtr<COMInterfaceType>& port;\r
-        WaitableEvent portOpened { true };\r
-    };\r
+           const auto ir = asyncOp->put_Completed (Callback<IAsyncOperationCompletedHandler<COMType*>> (std::move (callback)).Get());\r
+\r
+           if (FAILED (ir))\r
+               return;\r
+\r
+           if (future.wait_for (std::chrono::milliseconds (2000)) == std::future_status::ready)\r
+               comPort = future.get();\r
+        } }.join();\r
+    }\r
 \r
     //==============================================================================\r
     template <typename MIDIIOStaticsType, typename MIDIPort>\r
@@ -1565,12 +1595,7 @@ private:
               inputDevice (input),\r
               callback (cb)\r
         {\r
-            OpenMidiPortThread<IMidiInPortStatics, IMidiInPort, MidiInPort> portThread ("Open WinRT MIDI input port",\r
-                                                                                        deviceInfo.deviceID,\r
-                                                                                        service.midiInFactory,\r
-                                                                                        midiPort);\r
-            portThread.startThread();\r
-            portThread.waitForThreadToExit (-1);\r
+            openMidiPortThread<MidiInPort> ("Open WinRT MIDI input port", deviceInfo.deviceID, service.midiInFactory, midiPort);\r
 \r
             if (midiPort == nullptr)\r
             {\r
@@ -1582,7 +1607,18 @@ private:
 \r
             auto hr = midiPort->add_MessageReceived (\r
                 Callback<ITypedEventHandler<MidiInPort*, MidiMessageReceivedEventArgs*>> (\r
-                    [this] (IMidiInPort*, IMidiMessageReceivedEventArgs* args) { return midiInMessageReceived (args); }\r
+                    [self = checkedReference] (IMidiInPort*, IMidiMessageReceivedEventArgs* args)\r
+                    {\r
+                        HRESULT hr = S_OK;\r
+\r
+                        self->access ([&hr, args] (auto* ptr)\r
+                                      {\r
+                                         if (ptr != nullptr)\r
+                                             hr = ptr->midiInMessageReceived (args);\r
+                                      });\r
+\r
+                        return hr;\r
+                    }\r
                 ).Get(),\r
                 &midiInMessageToken);\r
 \r
@@ -1595,6 +1631,7 @@ private:
 \r
         ~WinRTInputWrapper()\r
         {\r
+            checkedReference->clear();\r
             disconnect();\r
         }\r
 \r
@@ -1706,6 +1743,8 @@ private:
         double startTime = 0;\r
         bool isStarted = false;\r
 \r
+        std::shared_ptr<CheckedReference<WinRTInputWrapper>> checkedReference = createCheckedReference (this);\r
+\r
         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WinRTInputWrapper);\r
     };\r
 \r
@@ -1716,12 +1755,7 @@ private:
         WinRTOutputWrapper (WinRTMidiService& service, const String& deviceIdentifier)\r
             : WinRTIOWrapper <IMidiOutPortStatics, IMidiOutPort> (*service.bleDeviceWatcher, *service.outputDeviceWatcher, deviceIdentifier)\r
         {\r
-            OpenMidiPortThread<IMidiOutPortStatics, IMidiOutPort, IMidiOutPort> portThread ("Open WinRT MIDI output port",\r
-                                                                                            deviceInfo.deviceID,\r
-                                                                                            service.midiOutFactory,\r
-                                                                                            midiPort);\r
-            portThread.startThread();\r
-            portThread.waitForThreadToExit (-1);\r
+            openMidiPortThread<IMidiOutPort> ("Open WinRT MIDI output port", deviceInfo.deviceID, service.midiOutFactory, midiPort);\r
 \r
             if (midiPort == nullptr)\r
                 throw std::runtime_error ("Timed out waiting for midi output port creation");\r
index b1a0aae158e01d259c8b47edffc4112a08f41a41..b516cdbba9b060cf3a8e532d2d0b5f07da48cb6f 100644 (file)
@@ -33,9 +33,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token")
 namespace WasapiClasses\r
 {\r
 \r
-static void logFailure (HRESULT hr)\r
+static void logFailure ([[maybe_unused]] HRESULT hr)\r
 {\r
-    ignoreUnused (hr);\r
     jassert (hr != (HRESULT) 0x800401f0); // If you hit this, it means you're trying to call from\r
                                           // a thread which hasn't been initialised with CoInitialize().\r
 \r
@@ -430,21 +429,23 @@ public:
         if (tempClient == nullptr)\r
             return;\r
 \r
-        WAVEFORMATEXTENSIBLE format;\r
+        auto format = getClientMixFormat (tempClient);\r
 \r
-        if (! getClientMixFormat (tempClient, format))\r
+        if (! format)\r
             return;\r
 \r
-        actualNumChannels = numChannels = format.Format.nChannels;\r
-        defaultSampleRate = format.Format.nSamplesPerSec;\r
+        defaultNumChannels = maxNumChannels = format->Format.nChannels;\r
+        defaultSampleRate = format->Format.nSamplesPerSec;\r
         rates.addUsingDefaultSort (defaultSampleRate);\r
-        mixFormatChannelMask = format.dwChannelMask;\r
+        defaultFormatChannelMask = format->dwChannelMask;\r
 \r
         if (isExclusiveMode (deviceMode))\r
-            findSupportedFormat (tempClient, defaultSampleRate, mixFormatChannelMask, format);\r
+            if (auto optFormat = findSupportedFormat (tempClient, defaultNumChannels, defaultSampleRate))\r
+                format = optFormat;\r
 \r
-        querySupportedBufferSizes (format, tempClient);\r
-        querySupportedSampleRates (format, tempClient);\r
+        querySupportedBufferSizes (*format, tempClient);\r
+        querySupportedSampleRates (*format, tempClient);\r
+        maxNumChannels = queryMaxNumChannels (tempClient);\r
     }\r
 \r
     virtual ~WASAPIDeviceBase()\r
@@ -459,7 +460,7 @@ public:
     {\r
         sampleRate = newSampleRate;\r
         channels = newChannels;\r
-        channels.setRange (actualNumChannels, channels.getHighestBit() + 1 - actualNumChannels, false);\r
+        channels.setRange (maxNumChannels, channels.getHighestBit() + 1 - maxNumChannels, false);\r
         numChannels = channels.getHighestBit() + 1;\r
 \r
         if (numChannels == 0)\r
@@ -533,10 +534,10 @@ public:
     WASAPIDeviceMode deviceMode;\r
 \r
     double sampleRate = 0, defaultSampleRate = 0;\r
-    int numChannels = 0, actualNumChannels = 0;\r
+    int numChannels = 0, actualNumChannels = 0, maxNumChannels = 0, defaultNumChannels = 0;\r
     int minBufferSize = 0, defaultBufferSize = 0, latencySamples = 0;\r
     int lowLatencyBufferSizeMultiple = 0, lowLatencyMaxBufferSize = 0;\r
-    DWORD mixFormatChannelMask = 0;\r
+    DWORD defaultFormatChannelMask = 0;\r
     Array<double> rates;\r
     HANDLE clientEvent = {};\r
     BigInteger channels;\r
@@ -627,17 +628,19 @@ private:
         return newClient;\r
     }\r
 \r
-    static bool getClientMixFormat (ComSmartPtr<IAudioClient>& client, WAVEFORMATEXTENSIBLE& format)\r
+    static std::optional<WAVEFORMATEXTENSIBLE> getClientMixFormat (ComSmartPtr<IAudioClient>& client)\r
     {\r
         WAVEFORMATEX* mixFormat = nullptr;\r
 \r
         if (! check (client->GetMixFormat (&mixFormat)))\r
-            return false;\r
+            return {};\r
+\r
+        WAVEFORMATEXTENSIBLE format;\r
 \r
         copyWavFormat (format, mixFormat);\r
         CoTaskMemFree (mixFormat);\r
 \r
-        return true;\r
+        return format;\r
     }\r
 \r
     //==============================================================================\r
@@ -710,12 +713,25 @@ private:
         int  bytesPerSampleContainer;\r
     };\r
 \r
-    bool tryFormat (const AudioSampleFormat sampleFormat, IAudioClient* clientToUse, double newSampleRate,\r
-                    DWORD newMixFormatChannelMask, WAVEFORMATEXTENSIBLE& format) const\r
+    static constexpr AudioSampleFormat formatsToTry[] =\r
+    {\r
+        { true,  32, 4 },\r
+        { false, 32, 4 },\r
+        { false, 24, 4 },\r
+        { false, 24, 3 },\r
+        { false, 20, 4 },\r
+        { false, 20, 3 },\r
+        { false, 16, 2 }\r
+    };\r
+\r
+    static std::optional<WAVEFORMATEXTENSIBLE> tryFormat (const AudioSampleFormat sampleFormat, IAudioClient* clientToUse,\r
+                                                          WASAPIDeviceMode mode, int newNumChannels, double newSampleRate,\r
+                                                          DWORD newMixFormatChannelMask)\r
     {\r
+        WAVEFORMATEXTENSIBLE format;\r
         zerostruct (format);\r
 \r
-        if (numChannels <= 2 && sampleFormat.bitsPerSampleToTry <= 16)\r
+        if (newNumChannels <= 2 && sampleFormat.bitsPerSampleToTry <= 16)\r
         {\r
             format.Format.wFormatTag = WAVE_FORMAT_PCM;\r
         }\r
@@ -726,7 +742,7 @@ private:
         }\r
 \r
         format.Format.nSamplesPerSec       = (DWORD) newSampleRate;\r
-        format.Format.nChannels            = (WORD) numChannels;\r
+        format.Format.nChannels            = (WORD) newNumChannels;\r
         format.Format.wBitsPerSample       = (WORD) (8 * sampleFormat.bytesPerSampleContainer);\r
         format.Samples.wValidBitsPerSample = (WORD) (sampleFormat.bitsPerSampleToTry);\r
         format.Format.nBlockAlign          = (WORD) (format.Format.nChannels * format.Format.wBitsPerSample / 8);\r
@@ -736,14 +752,14 @@ private:
 \r
         WAVEFORMATEX* nearestFormat = nullptr;\r
 \r
-        HRESULT hr = clientToUse->IsFormatSupported (isExclusiveMode (deviceMode) ? AUDCLNT_SHAREMODE_EXCLUSIVE\r
-                                                                                  : AUDCLNT_SHAREMODE_SHARED,\r
+        HRESULT hr = clientToUse->IsFormatSupported (isExclusiveMode (mode) ? AUDCLNT_SHAREMODE_EXCLUSIVE\r
+                                                                            : AUDCLNT_SHAREMODE_SHARED,\r
                                                      (WAVEFORMATEX*) &format,\r
-                                                     isExclusiveMode (deviceMode) ? nullptr\r
+                                                     isExclusiveMode (mode) ? nullptr\r
                                                                                   : &nearestFormat);\r
         logFailure (hr);\r
 \r
-        auto supportsSRC = supportsSampleRateConversion (deviceMode);\r
+        auto supportsSRC = supportsSampleRateConversion (mode);\r
 \r
         if (hr == S_FALSE\r
             && nearestFormat != nullptr\r
@@ -762,28 +778,49 @@ private:
         }\r
 \r
         CoTaskMemFree (nearestFormat);\r
-        return hr == S_OK;\r
+\r
+        if (hr != S_OK)\r
+            return {};\r
+\r
+        return format;\r
     }\r
 \r
-    bool findSupportedFormat (IAudioClient* clientToUse, double newSampleRate,\r
-                              DWORD newMixFormatChannelMask, WAVEFORMATEXTENSIBLE& format) const\r
+    std::optional<WAVEFORMATEXTENSIBLE> findSupportedFormat (IAudioClient* clientToUse, int newNumChannels, double newSampleRate) const\r
     {\r
-        static const AudioSampleFormat formats[] =\r
+        for (auto ch = newNumChannels; ch <= maxNumChannels; ++ch)\r
         {\r
-            { true,  32, 4 },\r
-            { false, 32, 4 },\r
-            { false, 24, 4 },\r
-            { false, 24, 3 },\r
-            { false, 20, 4 },\r
-            { false, 20, 3 },\r
-            { false, 16, 2 }\r
-        };\r
+            auto maskWithLowestNBitsSet = static_cast<DWORD> ((1 << ch) - 1);\r
+            auto mixFormatChannelMask = (ch == defaultNumChannels ? defaultFormatChannelMask : maskWithLowestNBitsSet);\r
 \r
-        for (int i = 0; i < numElementsInArray (formats); ++i)\r
-            if (tryFormat (formats[i], clientToUse, newSampleRate, newMixFormatChannelMask, format))\r
-                return true;\r
+            for (auto const& sampleFormat: formatsToTry)\r
+                if (auto format = tryFormat (sampleFormat, clientToUse, deviceMode, ch, newSampleRate, mixFormatChannelMask))\r
+                    return format;\r
+        }\r
 \r
-        return false;\r
+        return {};\r
+    }\r
+\r
+    int queryMaxNumChannels (IAudioClient* clientToUse) const\r
+    {\r
+        static constexpr auto maxNumChannelsToQuery = static_cast<int> (AudioChannelSet::maxChannelsOfNamedLayout);\r
+        const auto fallbackNumChannels = defaultNumChannels;\r
+\r
+        if (fallbackNumChannels >= maxNumChannelsToQuery)\r
+            return fallbackNumChannels;\r
+\r
+        auto result = fallbackNumChannels;\r
+\r
+        for (auto ch = maxNumChannelsToQuery; ch > result; --ch)\r
+        {\r
+            auto channelMask = static_cast<DWORD> ((1 << ch) - 1);\r
+\r
+            for (auto rate : rates)\r
+                for (auto const& sampleFormat: formatsToTry)\r
+                    if (auto format = tryFormat (sampleFormat, clientToUse, deviceMode, ch, rate, channelMask))\r
+                        result = jmax (static_cast<int> (format->Format.nChannels), result);\r
+        }\r
+\r
+        return result;\r
     }\r
 \r
     DWORD getStreamFlags()\r
@@ -851,19 +888,18 @@ private:
 \r
     bool tryInitialisingWithBufferSize (int bufferSizeSamples)\r
     {\r
-        WAVEFORMATEXTENSIBLE format;\r
 \r
-        if (findSupportedFormat (client, sampleRate, mixFormatChannelMask, format))\r
+        if (auto format = findSupportedFormat (client, numChannels, sampleRate))\r
         {\r
-            auto isInitialised = isLowLatencyMode (deviceMode) ? initialiseLowLatencyClient (bufferSizeSamples, format)\r
-                                                               : initialiseStandardClient   (bufferSizeSamples, format);\r
+            auto isInitialised = isLowLatencyMode (deviceMode) ? initialiseLowLatencyClient (bufferSizeSamples, *format)\r
+                                                               : initialiseStandardClient   (bufferSizeSamples, *format);\r
 \r
             if (isInitialised)\r
             {\r
-                actualNumChannels  = format.Format.nChannels;\r
-                const bool isFloat = format.Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format.SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;\r
-                bytesPerSample     = format.Format.wBitsPerSample / 8;\r
-                bytesPerFrame      = format.Format.nBlockAlign;\r
+                actualNumChannels  = format->Format.nChannels;\r
+                const bool isFloat = format->Format.wFormatTag == WAVE_FORMAT_EXTENSIBLE && format->SubFormat == KSDATAFORMAT_SUBTYPE_IEEE_FLOAT;\r
+                bytesPerSample     = format->Format.wBitsPerSample / 8;\r
+                bytesPerFrame      = format->Format.nBlockAlign;\r
 \r
                 updateFormat (isFloat);\r
 \r
@@ -1269,7 +1305,7 @@ public:
         StringArray outChannels;\r
 \r
         if (outputDevice != nullptr)\r
-            for (int i = 1; i <= outputDevice->actualNumChannels; ++i)\r
+            for (int i = 1; i <= outputDevice->maxNumChannels; ++i)\r
                 outChannels.add ("Output channel " + String (i));\r
 \r
         return outChannels;\r
@@ -1280,7 +1316,7 @@ public:
         StringArray inChannels;\r
 \r
         if (inputDevice != nullptr)\r
-            for (int i = 1; i <= inputDevice->actualNumChannels; ++i)\r
+            for (int i = 1; i <= inputDevice->maxNumChannels; ++i)\r
                 inChannels.add ("Input channel " + String (i));\r
 \r
         return inChannels;\r
@@ -1350,7 +1386,7 @@ public:
         shouldShutdown = false;\r
         deviceSampleRateChanged = false;\r
 \r
-        startThread (8);\r
+        startThread (Priority::high);\r
         Thread::sleep (5);\r
 \r
         if (inputDevice != nullptr && inputDevice->client != nullptr)\r
@@ -1515,7 +1551,7 @@ public:
                 const ScopedTryLock sl (startStopLock);\r
 \r
                 if (sl.isLocked() && isStarted)\r
-                    callback->audioDeviceIOCallbackWithContext (const_cast<const float**> (inputBuffers),\r
+                    callback->audioDeviceIOCallbackWithContext (inputBuffers,\r
                                                                 numInputBuffers,\r
                                                                 outputBuffers,\r
                                                                 numOutputBuffers,\r
@@ -1529,7 +1565,7 @@ public:
             {\r
                 // Note that this function is handed the input device so it can check for the event and make sure\r
                 // the input reservoir is filled up correctly even when bufferSize > device actualBufferSize\r
-                outputDevice->copyBuffers (const_cast<const float**> (outputBuffers), numOutputBuffers, bufferSize, inputDevice.get(), *this);\r
+                outputDevice->copyBuffers (outputBuffers, numOutputBuffers, bufferSize, inputDevice.get(), *this);\r
 \r
                 if (outputDevice->sampleRateHasChanged)\r
                 {\r
index 8270d20afd19aedd58a663f4ffdc19c7644f50b6..99eb16c13ec97fdf2ba9bb46ea327f96ebcd56f3 100644 (file)
@@ -56,11 +56,12 @@ void AudioSourcePlayer::setGain (const float newGain) noexcept
     gain = newGain;\r
 }\r
 \r
-void AudioSourcePlayer::audioDeviceIOCallback (const float** inputChannelData,\r
-                                               int totalNumInputChannels,\r
-                                               float** outputChannelData,\r
-                                               int totalNumOutputChannels,\r
-                                               int numSamples)\r
+void AudioSourcePlayer::audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
+                                                          int totalNumInputChannels,\r
+                                                          float* const* outputChannelData,\r
+                                                          int totalNumOutputChannels,\r
+                                                          int numSamples,\r
+                                                          [[maybe_unused]] const AudioIODeviceCallbackContext& context)\r
 {\r
     // these should have been prepared by audioDeviceAboutToStart()...\r
     jassert (sampleRate > 0 && bufferSize > 0);\r
index 65c19aac4b5f7e89f049b18195f43d9b4a9ecf54..8a975ee166cbe9a21435ead34f1e3f89810b8648 100644 (file)
@@ -79,12 +79,13 @@ public:
     float getGain() const noexcept                      { return gain; }\r
 \r
     //==============================================================================\r
-    /** Implementation of the AudioIODeviceCallback method. */\r
-    void audioDeviceIOCallback (const float** inputChannelData,\r
-                                int totalNumInputChannels,\r
-                                float** outputChannelData,\r
-                                int totalNumOutputChannels,\r
-                                int numSamples) override;\r
+    /** Implementation of the AudioIODeviceCallbackWithContext method. */\r
+    void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
+                                           int totalNumInputChannels,\r
+                                           float* const* outputChannelData,\r
+                                           int totalNumOutputChannels,\r
+                                           int numSamples,\r
+                                           const AudioIODeviceCallbackContext& context) override;\r
 \r
     /** Implementation of the AudioIODeviceCallback method. */\r
     void audioDeviceAboutToStart (AudioIODevice* device) override;\r
index a5b6329728ecc4e026809ced7151810e27dec4dd..6974d048a9dc85f450d94c0856d5777347f6ea52 100644 (file)
@@ -573,7 +573,7 @@ public:
     }\r
 \r
     //==============================================================================\r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
@@ -721,8 +721,7 @@ private:
     {\r
         using namespace AiffFileHelpers;\r
 \r
-        const bool couldSeekOk = output->setPosition (headerPosition);\r
-        ignoreUnused (couldSeekOk);\r
+        [[maybe_unused]] const bool couldSeekOk = output->setPosition (headerPosition);\r
 \r
         // if this fails, you've given it an output stream that can't seek! It needs\r
         // to be able to seek back to write the header\r
@@ -829,7 +828,7 @@ public:
     {\r
     }\r
 \r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
index e7ef336d6b338976aeb6f82528ce1c4bcf904fd5..079df3f3785426d636ebd8a9ae4d84e021d463c5 100644 (file)
@@ -502,7 +502,7 @@ public:
     }\r
 \r
     //==============================================================================\r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
index 8e389f52ce9a571e76c53a5f84e505580bf0911e..e743ae66827adbadd238b745384086bacaceab4d 100644 (file)
@@ -92,8 +92,8 @@ namespace FlacNamespace
 {\r
 #if JUCE_INCLUDE_FLAC_CODE || ! defined (JUCE_INCLUDE_FLAC_CODE)\r
 \r
- #undef VERSION\r
- #define VERSION "1.3.1"\r
+ #undef PACKAGE_VERSION\r
+ #define PACKAGE_VERSION "1.3.4"\r
 \r
  #define FLAC__NO_DLL 1\r
 \r
@@ -131,11 +131,17 @@ namespace FlacNamespace
   #define FLAC__HAS_X86INTRIN 1\r
  #endif\r
 \r
- #undef __STDC_LIMIT_MACROS\r
- #define __STDC_LIMIT_MACROS 1\r
  #define flac_max jmax\r
  #define flac_min jmin\r
- #undef DEBUG // (some flac code dumps debug trace if the app defines this macro)\r
+\r
+ #pragma push_macro ("DEBUG")\r
+ #pragma push_macro ("NDEBUG")\r
+ #undef  DEBUG  // (some flac code dumps debug trace if the app defines this macro)\r
+\r
+ #ifndef NDEBUG\r
+  #define NDEBUG // (some flac code prints cpu info if this isn't defined)\r
+ #endif\r
+\r
  #include "flac/all.h"\r
  #include "flac/libFLAC/bitmath.c"\r
  #include "flac/libFLAC/bitreader.c"\r
@@ -152,7 +158,11 @@ namespace FlacNamespace
  #include "flac/libFLAC/stream_encoder.c"\r
  #include "flac/libFLAC/stream_encoder_framing.c"\r
  #include "flac/libFLAC/window_flac.c"\r
- #undef VERSION\r
+\r
+ #pragma pop_macro ("DEBUG")\r
+ #pragma pop_macro ("NDEBUG")\r
+\r
+ #undef PACKAGE_VERSION\r
 \r
  JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
  JUCE_END_IGNORE_WARNINGS_MSVC\r
@@ -220,7 +230,7 @@ public:
         reservoir.setSize ((int) numChannels, 2 * (int) info.max_blocksize, false, false, true);\r
     }\r
 \r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         if (! ok)\r
@@ -486,8 +496,7 @@ public:
         packUint32 ((FLAC__uint32) info.total_samples, buffer + 14, 4);\r
         memcpy (buffer + 18, info.md5sum, 16);\r
 \r
-        const bool seekOk = output->setPosition (streamStartPos + 4);\r
-        ignoreUnused (seekOk);\r
+        [[maybe_unused]] const bool seekOk = output->setPosition (streamStartPos + 4);\r
 \r
         // if this fails, you've given it an output stream that can't seek! It needs\r
         // to be able to seek back to write the header\r
index 1120b0ffc8bae59539719857845e1d861c367366..00f31082dbc4e35361e52420a914d9bcbb10464a 100644 (file)
@@ -112,8 +112,8 @@ private:
 \r
         if (cp.start (processArgs))\r
         {\r
-            auto childOutput = cp.readAllProcessOutput();\r
-            DBG (childOutput); ignoreUnused (childOutput);\r
+            [[maybe_unused]] auto childOutput = cp.readAllProcessOutput();\r
+            DBG (childOutput);\r
 \r
             cp.waitForProcessToFinish (10000);\r
             return tempMP3.getFile().getSize() > 0;\r
index 7a287f9cc306fecf49225ae0d2dee4d8e6069667..d24df3dfae78dc6de019c3213a30884a39fed6a5 100644 (file)
@@ -2975,7 +2975,7 @@ public:
         }\r
     }\r
 \r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         if (destSamples == nullptr)\r
@@ -3033,7 +3033,7 @@ public:
             }\r
 \r
             const int numToCopy = jmin (decodedEnd - decodedStart, numSamples);\r
-            float* const* const dst = reinterpret_cast<float**> (destSamples);\r
+            float* const* const dst = reinterpret_cast<float* const*> (destSamples);\r
             memcpy (dst[0] + startOffsetInDestBuffer, decoded0 + decodedStart, (size_t) numToCopy * sizeof (float));\r
 \r
             if (numDestChannels > 1 && dst[1] != nullptr)\r
index b47c4a4d39a8eac890930cb44f267e19230af0e5..cf105e9bbeb19176be944de6f98a8b9833e2fb0e 100644 (file)
@@ -158,7 +158,7 @@ public:
     }\r
 \r
     //==============================================================================\r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         const auto getBufferedRange = [this] { return bufferedRange; };\r
index 20f0f492548d7fd02474c6581fb7640eb68fd367..c562882ca8783c0b805a4f6bea4b01fcb2e356ee 100644 (file)
@@ -1476,7 +1476,7 @@ public:
     }\r
 \r
     //==============================================================================\r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
@@ -1852,7 +1852,7 @@ public:
     {\r
     }\r
 \r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
index 9764a696977ffc9b32ab32cd6711119d795aecec..cb7af04cc3b45c14a95f09b82b5e85d7684b9195 100644 (file)
@@ -163,7 +163,7 @@ public:
             wmSyncReader->Close();\r
     }\r
 \r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         if (sampleRate <= 0)\r
@@ -262,7 +262,7 @@ private:
 \r
     void checkCoInitialiseCalled()\r
     {\r
-        ignoreUnused (CoInitialize (nullptr));\r
+        [[maybe_unused]] const auto result = CoInitialize (nullptr);\r
     }\r
 \r
     void scanFileForDetails()\r
index e02ab8f743112750a2c72f05986c0a9865b4cc56..a8c974d2873f8d392229a9de13d461a1c36fb4ea 100644 (file)
@@ -115,17 +115,17 @@ void ARAAudioSourceReader::willDestroyAudioSource (ARAAudioSource* audioSource)
     invalidate();\r
 }\r
 \r
-bool ARAAudioSourceReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool ARAAudioSourceReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                                         int64 startSampleInFile, int numSamples)\r
 {\r
     const auto destSize = (bitsPerSample / 8) * (size_t) numSamples;\r
     const auto bufferOffset = (int) (bitsPerSample / 8) * startOffsetInDestBuffer;\r
 \r
-    if (isValid() && hostReader != nullptr)\r
+    if (isValid())\r
     {\r
         const ScopedTryReadLock readLock (lock);\r
 \r
-        if (readLock.isLocked())\r
+        if (readLock.isLocked() && hostReader != nullptr)\r
         {\r
             for (size_t i = 0; i < tmpPtrs.size(); ++i)\r
             {\r
@@ -237,7 +237,7 @@ void ARAPlaybackRegionReader::invalidate()
     playbackRenderer.reset();\r
 }\r
 \r
-bool ARAPlaybackRegionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool ARAPlaybackRegionReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                                            int64 startSampleInFile, int numSamples)\r
 {\r
     bool success = false;\r
index c55a0636f7475b154a1cd62f4e36b73484c62657..6f231969cda60514575ffedabde9a20856973ce1 100644 (file)
@@ -83,7 +83,7 @@ public:
 \r
     ~ARAAudioSourceReader() override;\r
 \r
-    bool readSamples (int** destSamples,\r
+    bool readSamples (int* const* destSamples,\r
                       int numDestChannels,\r
                       int startOffsetInDestBuffer,\r
                       int64 startSampleInFile,\r
@@ -166,7 +166,7 @@ public:
     */\r
     void invalidate();\r
 \r
-    bool readSamples (int** destSamples,\r
+    bool readSamples (int* const* destSamples,\r
                       int numDestChannels,\r
                       int startOffsetInDestBuffer,\r
                       int64 startSampleInFile,\r
index 21e6e82b161dd60a93c54071646df0380a8d198f..92998539b9058c114777a7998ac2b875357ccf15 100644 (file)
@@ -86,7 +86,7 @@ bool AudioFormatReader::read (int* const* destChannels,
     if (numSamplesToRead <= 0)\r
         return true;\r
 \r
-    if (! readSamples (const_cast<int**> (destChannels),\r
+    if (! readSamples (destChannels,\r
                        jmin ((int) numChannels, numDestChannels), startOffsetInDestBuffer,\r
                        startSampleInSource, numSamplesToRead))\r
         return false;\r
index eff786911512f2ab01ce1d191891239dc5ceaad9..25af44c28386db84d3ae1eabdd95e225a5eb7542 100644 (file)
@@ -267,7 +267,7 @@ public:
                                          to begin reading. This value is guaranteed to be >= 0.\r
         @param numSamples                the number of samples to read\r
     */\r
-    virtual bool readSamples (int** destChannels,\r
+    virtual bool readSamples (int* const* destChannels,\r
                               int numDestChannels,\r
                               int startOffsetInDestBuffer,\r
                               int64 startSampleInFile,\r
@@ -306,7 +306,7 @@ protected:
     /** Used by AudioFormatReader subclasses to clear any parts of the data blocks that lie\r
         beyond the end of their available length.\r
     */\r
-    static void clearSamplesBeyondAvailableLength (int** destChannels, int numDestChannels,\r
+    static void clearSamplesBeyondAvailableLength (int* const* destChannels, int numDestChannels,\r
                                                    int startOffsetInDestBuffer, int64 startSampleInFile,\r
                                                    int& numSamples, int64 fileLengthInSamples)\r
     {\r
index 8c16177e26ee62edc804237257e39eafab101182..530c4bbca7ef2419d2568830c6a2d3a562504342 100644 (file)
@@ -50,7 +50,7 @@ AudioSubsectionReader::~AudioSubsectionReader()
 }\r
 \r
 //==============================================================================\r
-bool AudioSubsectionReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool AudioSubsectionReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                                          int64 startSampleInFile, int numSamples)\r
 {\r
     clearSamplesBeyondAvailableLength (destSamples, numDestChannels, startOffsetInDestBuffer,\r
index 52d4ba6e72830e4ce434bb05c3bbf833e21c2fab..5b9cdddb38fb3367457316df136ea1ff4a4b0d7b 100644 (file)
@@ -66,7 +66,7 @@ public:
 \r
 \r
     //==============================================================================\r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override;\r
 \r
     void readMaxLevels (int64 startSample, int64 numSamples,\r
index d59b279afb5d3f4764bc6075e27304adc2904477..95da52c92013c256b7596bfeaa5bd3fd492a9c56 100644 (file)
@@ -53,7 +53,7 @@ void BufferingAudioReader::setReadTimeout (int timeoutMilliseconds) noexcept
     timeoutMs = timeoutMilliseconds;\r
 }\r
 \r
-bool BufferingAudioReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool BufferingAudioReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                                         int64 startSampleInFile, int numSamples)\r
 {\r
     auto startTime = Time::getMillisecondCounter();\r
@@ -218,7 +218,7 @@ struct TestAudioFormatReader  : public AudioFormatReader
         numChannels           = (unsigned int) buffer.getNumChannels();\r
     }\r
 \r
-    bool readSamples (int** destChannels, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destChannels, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override\r
     {\r
         clearSamplesBeyondAvailableLength (destChannels, numDestChannels, startOffsetInDestBuffer,\r
@@ -254,7 +254,7 @@ public:
     void runTest() override\r
     {\r
         TimeSliceThread timeSlice ("TestBackgroundThread");\r
-        timeSlice.startThread (5);\r
+        timeSlice.startThread (Thread::Priority::normal);\r
 \r
         beginTest ("Timeout");\r
         {\r
@@ -270,7 +270,7 @@ public:
                     numChannels           = 2;\r
                 }\r
 \r
-                bool readSamples (int**, int, int, int64, int) override\r
+                bool readSamples (int* const*, int, int, int64, int) override\r
                 {\r
                     Thread::sleep (100);\r
                     return true;\r
index 8414c18a55d793d084b138d0f1322473394bf46a..b16e2bdcea3843ba0e477cd8c2d5f8c1301d39ce 100644 (file)
@@ -63,7 +63,7 @@ public:
     void setReadTimeout (int timeoutMilliseconds) noexcept;\r
 \r
     //==============================================================================\r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override;\r
 \r
 private:\r
index 8eb69c2c9684093e9ffaf0d653f83bcbb2c563d7..aa26e9fa2af2a239dcb2c7579a3c583246a4e8ef 100644 (file)
 \r
   ID:                 juce_audio_formats\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE audio file format codecs\r
   description:        Classes for reading and writing various audio file formats.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_audio_basics\r
   OSXFrameworks:      CoreAudio CoreMIDI QuartzCore AudioToolbox\r
index 9abcb113756315ed956282e60ee13ad1b5339602..f0c7228853dfe64e5f71fbf8f52b79836c7e5cfa 100644 (file)
@@ -43,7 +43,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wnon-virtual-dtor",
                                      "-Wzero-as-null-pointer-constant",\r
                                      "-Winconsistent-missing-destructor-override",\r
                                      "-Wfour-char-constants",\r
-                                     "-Wtautological-overlap-compare")\r
+                                     "-Wtautological-overlap-compare",\r
+                                     "-Wdeprecated-declarations")\r
 \r
 #include <AAX_Version.h>\r
 \r
@@ -70,11 +71,19 @@ static_assert (AAX_SDK_CURRENT_REVISION >= AAX_SDK_2p3p0_REVISION, "JUCE require
 #include <AAX_IFeatureInfo.h>\r
 #include <AAX_UIDs.h>\r
 \r
-#ifdef AAX_SDK_2p3p1_REVISION\r
- #if AAX_SDK_CURRENT_REVISION >= AAX_SDK_2p3p1_REVISION\r
-  #include <AAX_Exception.h>\r
-  #include <AAX_Assert.h>\r
- #endif\r
+#if defined (AAX_SDK_2p3p1_REVISION) && AAX_SDK_2p3p1_REVISION <= AAX_SDK_CURRENT_REVISION\r
+ #include <AAX_Exception.h>\r
+ #include <AAX_Assert.h>\r
+#endif\r
+\r
+#if defined (AAX_SDK_2p4p0_REVISION) && AAX_SDK_2p4p0_REVISION <= AAX_SDK_CURRENT_REVISION\r
+ #define JUCE_AAX_HAS_TRANSPORT_NOTIFICATION 1\r
+#else\r
+ #define JUCE_AAX_HAS_TRANSPORT_NOTIFICATION 0\r
+#endif\r
+\r
+#if JUCE_AAX_HAS_TRANSPORT_NOTIFICATION\r
+ #include <AAX_TransportTypes.h>\r
 #endif\r
 \r
 JUCE_END_IGNORE_WARNINGS_MSVC\r
@@ -738,8 +747,6 @@ namespace AAXClasses
 \r
         static AAX_CEffectParameters* AAX_CALLBACK Create()\r
         {\r
-            PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AAX;\r
-\r
             if (PluginHostType::jucePlugInIsRunningInAudioSuiteFn == nullptr)\r
             {\r
                 PluginHostType::jucePlugInIsRunningInAudioSuiteFn = [] (AudioProcessor& processor)\r
@@ -879,7 +886,7 @@ namespace AAXClasses
 \r
                 case JUCEAlgorithmIDs::preparedFlag:\r
                 {\r
-                    const_cast<JuceAAX_Processor*>(this)->preparePlugin();\r
+                    const_cast<JuceAAX_Processor*> (this)->preparePlugin();\r
 \r
                     auto numObjects = dataSize / sizeof (uint32_t);\r
                     auto* objects = static_cast<uint32_t*> (data);\r
@@ -1048,14 +1055,16 @@ namespace AAXClasses
                 return transport.GetCurrentTempo (&bpm) == AAX_SUCCESS ? makeOptional (bpm) : nullopt;\r
             }());\r
 \r
-            info.setTimeSignature ([&]\r
+            const auto signature = [&]\r
             {\r
                 int32_t num = 4, den = 4;\r
 \r
                 return transport.GetCurrentMeter (&num, &den) == AAX_SUCCESS\r
-                       ? makeOptional (TimeSignature { (int) num, (int) den })\r
-                       : nullopt;\r
-            }());\r
+                     ? makeOptional (TimeSignature { (int) num, (int) den })\r
+                     : nullopt;\r
+            }();\r
+\r
+            info.setTimeSignature (signature);\r
 \r
             info.setIsPlaying ([&]\r
             {\r
@@ -1064,27 +1073,31 @@ namespace AAXClasses
                 return transport.IsTransportPlaying (&isPlaying) == AAX_SUCCESS && isPlaying;\r
             }());\r
 \r
-            info.setTimeInSamples ([&]\r
+            info.setIsRecording (recordingState.get().orFallback (false));\r
+\r
+            const auto optionalTimeInSamples = [&info, &transport]\r
             {\r
                 int64_t timeInSamples = 0;\r
-\r
                 return ((! info.getIsPlaying() && transport.GetTimelineSelectionStartPosition (&timeInSamples) == AAX_SUCCESS)\r
-                        || transport.GetCurrentNativeSampleLocation (&timeInSamples) == AAX_SUCCESS)\r
-                            ? makeOptional (timeInSamples)\r
-                            : nullopt;\r
-            }());\r
+                                                    || transport.GetCurrentNativeSampleLocation (&timeInSamples) == AAX_SUCCESS)\r
+                                                 ? makeOptional (timeInSamples)\r
+                                                 : nullopt;\r
+            }();\r
 \r
-            info.setTimeInSeconds ((float) info.getTimeInSamples().orFallback (0) / sampleRate);\r
+            info.setTimeInSamples (optionalTimeInSamples);\r
+            info.setTimeInSeconds ((float) optionalTimeInSamples.orFallback (0) / sampleRate);\r
 \r
-            info.setPpqPosition ([&]\r
+            const auto tickPosition = [&]\r
             {\r
                 int64_t ticks = 0;\r
 \r
-                return ((info.getIsPlaying() && transport.GetCustomTickPosition (&ticks, info.getTimeInSamples().orFallback (0))) == AAX_SUCCESS)\r
-                        || transport.GetCurrentTickPosition (&ticks) == AAX_SUCCESS\r
-                            ? makeOptional (ticks / 960000.0)\r
-                            : nullopt;\r
-            }());\r
+                return ((info.getIsPlaying() && transport.GetCustomTickPosition (&ticks, optionalTimeInSamples.orFallback (0))) == AAX_SUCCESS)\r
+                       || transport.GetCurrentTickPosition (&ticks) == AAX_SUCCESS\r
+                     ? makeOptional (ticks)\r
+                     : nullopt;\r
+            }();\r
+\r
+            info.setPpqPosition (tickPosition.hasValue() ? makeOptional (static_cast<double> (*tickPosition) / 960'000.0) : nullopt);\r
 \r
             bool isLooping = false;\r
             int64_t loopStartTick = 0, loopEndTick = 0;\r
@@ -1139,7 +1152,29 @@ namespace AAXClasses
             }\r
 \r
             const auto effectiveRate = info.getFrameRate().hasValue() ? info.getFrameRate()->getEffectiveRate() : 0.0;\r
-            info.setEditOriginTime (effectiveRate != 0.0 ? makeOptional (offset / effectiveRate) : nullopt);\r
+            info.setEditOriginTime (makeOptional (effectiveRate != 0.0 ? offset / effectiveRate : offset));\r
+\r
+            {\r
+                int32_t bars{}, beats{};\r
+                int64_t displayTicks{};\r
+\r
+                if (optionalTimeInSamples.hasValue()\r
+                    && transport.GetBarBeatPosition (&bars, &beats, &displayTicks, *optionalTimeInSamples) == AAX_SUCCESS)\r
+                {\r
+                    info.setBarCount (bars);\r
+\r
+                    if (signature.hasValue())\r
+                    {\r
+                        const auto ticksSinceBar = static_cast<int64_t> (((beats - 1) * 4 * 960'000) / signature->denominator) + displayTicks;\r
+\r
+                        if (tickPosition.hasValue() && ticksSinceBar <= tickPosition)\r
+                        {\r
+                            const auto barStartInTicks = static_cast<double> (*tickPosition - ticksSinceBar);\r
+                            info.setPpqPositionOfLastBarStart (barStartInTicks / 960'000.0);\r
+                        }\r
+                    }\r
+                }\r
+            }\r
 \r
             return info;\r
         }\r
@@ -1162,18 +1197,9 @@ namespace AAXClasses
 \r
             if (details.parameterInfoChanged)\r
             {\r
-                auto numParameters = juceParameters.getNumParameters();\r
-\r
-                for (int i = 0; i < numParameters; ++i)\r
-                {\r
-                    if (auto* p = mParameterManager.GetParameterByID (getAAXParamIDFromJuceIndex (i)))\r
-                    {\r
-                        auto newName = juceParameters.getParamForIndex (i)->getName (31);\r
-\r
-                        if (p->Name() != newName.toRawUTF8())\r
-                            p->SetName (AAX_CString (newName.toRawUTF8()));\r
-                    }\r
-                }\r
+                for (const auto* param : juceParameters)\r
+                    if (auto* aaxParam = mParameterManager.GetParameterByID (getAAXParamIDFromJuceIndex (param->getParameterIndex())))\r
+                        syncParameterAttributes (aaxParam, param);\r
             }\r
 \r
             if (details.latencyChanged)\r
@@ -1233,6 +1259,16 @@ namespace AAXClasses
                     updateSidechainState();\r
                     break;\r
                 }\r
+\r
+               #if JUCE_AAX_HAS_TRANSPORT_NOTIFICATION\r
+                case AAX_eNotificationEvent_TransportStateChanged:\r
+                    if (data != nullptr)\r
+                    {\r
+                        const auto& info = *static_cast<const AAX_TransportStateInfo_V1*> (data);\r
+                        recordingState.set (info.mIsRecording);\r
+                    }\r
+                    break;\r
+               #endif\r
             }\r
 \r
             return AAX_CEffectParameters::NotificationReceived (type, data, size);\r
@@ -1245,7 +1281,7 @@ namespace AAXClasses
             if (idx < mainNumIns)\r
                 return inputs[inputLayoutMap[idx]];\r
 \r
-            return (sidechain != -1 ? inputs[sidechain] : sideChainBuffer.getData());\r
+            return (sidechain != -1 ? inputs[sidechain] : sideChainBuffer.data());\r
         }\r
 \r
         void process (const float* const* inputs, float* const* outputs, const int sideChainBufferIdx,\r
@@ -1507,11 +1543,10 @@ namespace AAXClasses
         friend void AAX_CALLBACK AAXClasses::algorithmProcessCallback (JUCEAlgorithmContext* const instancesBegin[], const void* const instancesEnd);\r
 \r
         void process (float* const* channels, const int numChans, const int bufferSize,\r
-                      const bool bypass, AAX_IMIDINode* midiNodeIn, AAX_IMIDINode* midiNodesOut)\r
+                      const bool bypass, [[maybe_unused]] AAX_IMIDINode* midiNodeIn, [[maybe_unused]] AAX_IMIDINode* midiNodesOut)\r
         {\r
             AudioBuffer<float> buffer (channels, numChans, bufferSize);\r
             midiBuffer.clear();\r
-            ignoreUnused (midiNodeIn, midiNodesOut);\r
 \r
            #if JucePlugin_WantsMidiInput || JucePlugin_IsMidiEffect\r
             {\r
@@ -1533,19 +1568,15 @@ namespace AAXClasses
                 if (lastBufferSize != bufferSize)\r
                 {\r
                     lastBufferSize = bufferSize;\r
-                    pluginInstance->setRateAndBufferSizeDetails (sampleRate, bufferSize);\r
+                    pluginInstance->setRateAndBufferSizeDetails (sampleRate, lastBufferSize);\r
 \r
+                    // we only call prepareToPlay here if the new buffer size is larger than\r
+                    // the one used last time prepareToPlay was called.\r
+                    // currently, this should never actually happen, because as of Pro Tools 12,\r
+                    // the maximum possible value is 1024, and we call prepareToPlay with that\r
+                    // value during initialisation.\r
                     if (bufferSize > maxBufferSize)\r
-                    {\r
-                        // we only call prepareToPlay here if the new buffer size is larger than\r
-                        // the one used last time prepareToPlay was called.\r
-                        // currently, this should never actually happen, because as of Pro Tools 12,\r
-                        // the maximum possible value is 1024, and we call prepareToPlay with that\r
-                        // value during initialisation.\r
-                        pluginInstance->prepareToPlay (sampleRate, bufferSize);\r
-                        maxBufferSize = bufferSize;\r
-                        sideChainBuffer.calloc (static_cast<size_t> (maxBufferSize));\r
-                    }\r
+                        prepareProcessorWithSampleRateAndBufferSize (sampleRate, bufferSize);\r
                 }\r
 \r
                 if (bypass && pluginInstance->getBypassParameter() == nullptr)\r
@@ -1810,14 +1841,10 @@ namespace AAXClasses
                     audioProcessor.releaseResources();\r
                 }\r
 \r
-                audioProcessor.setRateAndBufferSizeDetails (sampleRate, lastBufferSize);\r
-                audioProcessor.prepareToPlay (sampleRate, lastBufferSize);\r
-                maxBufferSize = lastBufferSize;\r
+                prepareProcessorWithSampleRateAndBufferSize (sampleRate, lastBufferSize);\r
 \r
                 midiBuffer.ensureSize (2048);\r
                 midiBuffer.clear();\r
-\r
-                sideChainBuffer.calloc (static_cast<size_t> (maxBufferSize));\r
             }\r
 \r
             check (Controller()->SetSignalLatency (audioProcessor.getLatencySamples()));\r
@@ -1879,6 +1906,16 @@ namespace AAXClasses
             }\r
         }\r
 \r
+        void prepareProcessorWithSampleRateAndBufferSize (double sr, int bs)\r
+        {\r
+            maxBufferSize = jmax (maxBufferSize, bs);\r
+\r
+            auto& audioProcessor = getPluginInstance();\r
+            audioProcessor.setRateAndBufferSizeDetails (sr, maxBufferSize);\r
+            audioProcessor.prepareToPlay (sr, maxBufferSize);\r
+            sideChainBuffer.resize (static_cast<size_t> (maxBufferSize));\r
+        }\r
+\r
         //==============================================================================\r
         void updateSidechainState()\r
         {\r
@@ -1886,7 +1923,7 @@ namespace AAXClasses
                 return;\r
 \r
             auto& audioProcessor = getPluginInstance();\r
-            bool sidechainActual = audioProcessor.getChannelCountOfBus (true, 1) > 0;\r
+            const auto sidechainActual = audioProcessor.getChannelCountOfBus (true, 1) > 0;\r
 \r
             if (hasSidechain && canDisableSidechain && sidechainDesired != sidechainActual)\r
             {\r
@@ -1902,7 +1939,7 @@ namespace AAXClasses
                     bus->setCurrentLayout (lastSideChainState ? AudioChannelSet::mono()\r
                                                               : AudioChannelSet::disabled());\r
 \r
-                audioProcessor.prepareToPlay (audioProcessor.getSampleRate(), audioProcessor.getBlockSize());\r
+                prepareProcessorWithSampleRateAndBufferSize (audioProcessor.getSampleRate(), maxBufferSize);\r
                 isPrepared = true;\r
             }\r
 \r
@@ -2064,22 +2101,97 @@ namespace AAXClasses
             return defaultLayout;\r
         }\r
 \r
+        void syncParameterAttributes (AAX_IParameter* aaxParam, const AudioProcessorParameter* juceParam)\r
+        {\r
+            if (juceParam == nullptr)\r
+                return;\r
+\r
+            {\r
+                auto newName = juceParam->getName (31);\r
+\r
+                if (aaxParam->Name() != newName.toRawUTF8())\r
+                    aaxParam->SetName (AAX_CString (newName.toRawUTF8()));\r
+            }\r
+\r
+            {\r
+                auto newType = juceParam->isDiscrete() ? AAX_eParameterType_Discrete : AAX_eParameterType_Continuous;\r
+\r
+                if (aaxParam->GetType() != newType)\r
+                    aaxParam->SetType (newType);\r
+            }\r
+\r
+            {\r
+                auto newNumSteps = static_cast<uint32_t> (juceParam->getNumSteps());\r
+\r
+                if (aaxParam->GetNumberOfSteps() != newNumSteps)\r
+                    aaxParam->SetNumberOfSteps (newNumSteps);\r
+            }\r
+\r
+            {\r
+                auto defaultValue = juceParam->getDefaultValue();\r
+\r
+                if (! approximatelyEqual (static_cast<float> (aaxParam->GetNormalizedDefaultValue()), defaultValue))\r
+                    aaxParam->SetNormalizedDefaultValue (defaultValue);\r
+            }\r
+        }\r
+\r
         //==============================================================================\r
         ScopedJuceInitialiser_GUI libraryInitialiser;\r
 \r
         std::unique_ptr<AudioProcessor> pluginInstance;\r
 \r
+        static constexpr auto maxSamplesPerBlock = 1 << AAX_eAudioBufferLength_Max;\r
+\r
         bool isPrepared = false;\r
         MidiBuffer midiBuffer;\r
         Array<float*> channelList;\r
         int32_t juceChunkIndex = 0, numSetDirtyCalls = 0;\r
         AAX_CSampleRate sampleRate = 0;\r
-        int lastBufferSize = 1024, maxBufferSize = 1024;\r
+        int lastBufferSize = maxSamplesPerBlock, maxBufferSize = maxSamplesPerBlock;\r
         bool hasSidechain = false, canDisableSidechain = false, lastSideChainState = false;\r
 \r
+        /*  Pro Tools 2021 sends TransportStateChanged on the main thread, but we read\r
+            the recording state on the audio thread.\r
+            I'm not sure whether Pro Tools ensures that these calls are mutually\r
+            exclusive, so to ensure there are no data races, we store the recording\r
+            state in an atomic int and convert it to/from an Optional<bool> as necessary.\r
+        */\r
+        class RecordingState\r
+        {\r
+        public:\r
+            /*  This uses Optional rather than std::optional for consistency with get() */\r
+            void set (const Optional<bool> newState)\r
+            {\r
+                state.store (newState.hasValue() ? (flagValid | (*newState ? flagActive : 0))\r
+                                                 : 0,\r
+                             std::memory_order_relaxed);\r
+            }\r
+\r
+            /*  PositionInfo::setIsRecording takes an Optional<bool>, so we use that type rather\r
+                than std::optional to avoid having to convert.\r
+            */\r
+            Optional<bool> get() const\r
+            {\r
+                const auto loaded = state.load (std::memory_order_relaxed);\r
+                return ((loaded & flagValid) != 0) ? makeOptional ((loaded & flagActive) != 0)\r
+                                                   : nullopt;\r
+            }\r
+\r
+        private:\r
+            enum RecordingFlags\r
+            {\r
+                flagValid  = 1 << 0,\r
+                flagActive = 1 << 1\r
+            };\r
+\r
+            std::atomic<int> state { 0 };\r
+        };\r
+\r
+        RecordingState recordingState;\r
+\r
         std::atomic<bool> processingSidechainChange, sidechainDesired;\r
 \r
-        HeapBlock<float> sideChainBuffer;\r
+        std::vector<float> sideChainBuffer;\r
         Array<int> inputLayoutMap, outputLayoutMap;\r
 \r
         Array<String> aaxParamIDs;\r
@@ -2303,6 +2415,10 @@ namespace AAXClasses
         properties->AddProperty (AAX_eProperty_SupportsSaveRestore, false);\r
        #endif\r
 \r
+       #if JUCE_AAX_HAS_TRANSPORT_NOTIFICATION\r
+        properties->AddProperty (AAX_eProperty_ObservesTransportState, true);\r
+       #endif\r
+\r
         if (fullLayout.getChannelSet (true, 1) == AudioChannelSet::mono())\r
         {\r
             check (desc.AddSideChainIn (JUCEAlgorithmIDs::sideChainBuffers));\r
@@ -2365,10 +2481,9 @@ namespace AAXClasses
         return (AAX_STEM_FORMAT_INDEX (stemFormat) <= 12);\r
     }\r
 \r
-    static void getPlugInDescription (AAX_IEffectDescriptor& descriptor, const AAX_IFeatureInfo* featureInfo)\r
+    static void getPlugInDescription (AAX_IEffectDescriptor& descriptor, [[maybe_unused]] const AAX_IFeatureInfo* featureInfo)\r
     {\r
-        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_AAX;\r
-        std::unique_ptr<AudioProcessor> plugin (createPluginFilterOfType (AudioProcessor::wrapperType_AAX));\r
+        auto plugin = createPluginFilterOfType (AudioProcessor::wrapperType_AAX);\r
         auto numInputBuses  = plugin->getBusCount (true);\r
         auto numOutputBuses = plugin->getBusCount (false);\r
 \r
@@ -2398,7 +2513,6 @@ namespace AAXClasses
        #if JucePlugin_IsMidiEffect\r
         // MIDI effect plug-ins do not support any audio channels\r
         jassert (numInputBuses == 0 && numOutputBuses == 0);\r
-        ignoreUnused (featureInfo);\r
 \r
         if (auto* desc = descriptor.NewComponentDescriptor())\r
         {\r
index d1b055e69724bfd62e2d28391bed82ef871fa358..44f39beb93b79cdb48328b061e2aeec3696dfe44 100644 (file)
@@ -37,6 +37,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4100)
 #include <ARA_Library/PlugIn/ARAPlug.cpp>\r
 #include <ARA_Library/Dispatch/ARAPlugInDispatch.cpp>\r
 #include <ARA_Library/Utilities/ARAPitchInterpretation.cpp>\r
+#include <ARA_Library/Utilities/ARAChannelArrangement.cpp>\r
 \r
 JUCE_END_IGNORE_WARNINGS_MSVC\r
 JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
diff --git a/modules/juce_audio_plugin_client/AUResources.r b/modules/juce_audio_plugin_client/AUResources.r
deleted file mode 100644 (file)
index 30fb387..0000000
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
-     File: AUResources.r
- Abstract: AUResources.r
-  Version: 1.1
- Disclaimer: IMPORTANT:  This Apple software is supplied to you by Apple
- Inc. ("Apple") in consideration of your agreement to the following
- terms, and your use, installation, modification or redistribution of
- this Apple software constitutes acceptance of these terms.  If you do
- not agree with these terms, please do not use, install, modify or
- redistribute this Apple software.
- In consideration of your agreement to abide by the following terms, and
- subject to these terms, Apple grants you a personal, non-exclusive
- license, under Apple's copyrights in this original Apple software (the
- "Apple Software"), to use, reproduce, modify and redistribute the Apple
- Software, with or without modifications, in source and/or binary forms;
- provided that if you redistribute the Apple Software in its entirety and
- without modifications, you must retain this notice and the following
- text and disclaimers in all such redistributions of the Apple Software.
- Neither the name, trademarks, service marks or logos of Apple Inc. may
- be used to endorse or promote products derived from the Apple Software
- without specific prior written permission from Apple.  Except as
- expressly stated in this notice, no other rights or licenses, express or
- implied, are granted by Apple herein, including but not limited to any
- patent rights that may be infringed by your derivative works or by other
- works in which the Apple Software may be incorporated.
- The Apple Software is provided by Apple on an "AS IS" basis.  APPLE
- MAKES NO WARRANTIES, EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION
- THE IMPLIED WARRANTIES OF NON-INFRINGEMENT, MERCHANTABILITY AND FITNESS
- FOR A PARTICULAR PURPOSE, REGARDING THE APPLE SOFTWARE OR ITS USE AND
- OPERATION ALONE OR IN COMBINATION WITH YOUR PRODUCTS.
- IN NO EVENT SHALL APPLE BE LIABLE FOR ANY SPECIAL, INDIRECT, INCIDENTAL
- OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
- INTERRUPTION) ARISING IN ANY WAY OUT OF THE USE, REPRODUCTION,
- MODIFICATION AND/OR DISTRIBUTION OF THE APPLE SOFTWARE, HOWEVER CAUSED
- AND WHETHER UNDER THEORY OF CONTRACT, TORT (INCLUDING NEGLIGENCE),
- STRICT LIABILITY OR OTHERWISE, EVEN IF APPLE HAS BEEN ADVISED OF THE
- POSSIBILITY OF SUCH DAMAGE.
- Copyright (C) 2014 Apple Inc. All Rights Reserved.
-*/
-/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-//     AUResources.r
-//
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
-
-/* sample macro definitions -- all of these symbols must be defined
-#define RES_ID                 kHALOutputResID
-#define COMP_TYPE              kAudioUnitComponentType
-#define COMP_SUBTYPE   kAudioUnitOutputSubType
-#define COMP_MANUF             kAudioUnitAudioHardwareOutputSubSubType
-#define VERSION                        0x00010000
-#define NAME                   "AudioHALOutput"
-#define DESCRIPTION            "Audio hardware output AudioUnit"
-#define ENTRY_POINT            "AUHALEntry"
-*/
-#define UseExtendedThingResource 1
-
-#include <CoreServices/CoreServices.r>
-
-// this is a define used to indicate that a component has no static data that would mean 
-// that no more than one instance could be open at a time - never been true for AUs
-#ifndef cmpThreadSafeOnMac
-#define cmpThreadSafeOnMac     0x10000000
-#endif
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-resource 'STR ' (RES_ID, purgeable) {
-       NAME
-};
-
-resource 'STR ' (RES_ID + 1, purgeable) {
-       DESCRIPTION
-};
-
-resource 'dlle' (RES_ID) {
-       ENTRY_POINT
-};
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-resource 'thng' (RES_ID, NAME) {
-       COMP_TYPE,
-       COMP_SUBTYPE,
-       COMP_MANUF,
-       0, 0, 0, 0,                                                             //      no 68K
-       'STR ', RES_ID,
-       'STR ', RES_ID + 1,
-       0,      0,                      /* icon */
-       VERSION,
-       componentHasMultiplePlatforms | componentDoAutoVersion,
-       0,
-       {
-       #if defined(ppc_YES)
-                       cmpThreadSafeOnMac,
-                       'dlle', RES_ID, platformPowerPCNativeEntryPoint
-                       #define NeedLeadingComma 1
-       #endif
-       #if defined(ppc64_YES)
-               #if defined(NeedLeadingComma)
-                       ,
-               #endif
-                       cmpThreadSafeOnMac,
-                       'dlle', RES_ID, platformPowerPC64NativeEntryPoint
-                       #define NeedLeadingComma 1
-       #endif
-       #if defined(i386_YES)
-               #if defined(NeedLeadingComma)
-                       ,
-               #endif
-                       cmpThreadSafeOnMac,
-                       'dlle', RES_ID, platformIA32NativeEntryPoint
-                       #define NeedLeadingComma 1
-       #endif
-       #if defined(x86_64_YES)
-               #if defined(NeedLeadingComma)
-                       ,
-               #endif
-                       cmpThreadSafeOnMac,
-                       'dlle', RES_ID, 8
-                       #define NeedLeadingComma 1
-       #endif
-       // JUCE CHANGE STARTS HERE
-       #if defined(arm64_YES)
-               #if defined(NeedLeadingComma)
-                       ,
-               #endif
-                       cmpThreadSafeOnMac,
-                       'dlle', RES_ID, 9
-                       #define NeedLeadingComma 1
-       #endif
-    // JUCE CHANGE ENDS HERE
-       }
-};
-
-#undef RES_ID
-#undef COMP_TYPE
-#undef COMP_SUBTYPE
-#undef COMP_MANUF
-#undef VERSION
-#undef NAME
-#undef DESCRIPTION
-#undef ENTRY_POINT
-#undef NeedLeadingComma
diff --git a/modules/juce_audio_plugin_client/CMakeLists.txt b/modules/juce_audio_plugin_client/CMakeLists.txt
deleted file mode 100644 (file)
index 116346c..0000000
+++ /dev/null
@@ -1,29 +0,0 @@
-# ==============================================================================
-#
-#  This file is part of the JUCE library.
-#  Copyright (c) 2022 - Raw Material Software Limited
-#
-#  JUCE is an open source library subject to commercial or open-source
-#  licensing.
-#
-#  By using JUCE, you agree to the terms of both the JUCE 7 End-User License
-#  Agreement and JUCE Privacy Policy.
-#
-#  End User License Agreement: www.juce.com/juce-7-licence
-#  Privacy Policy: www.juce.com/juce-privacy-policy
-#
-#  Or: You may also use this code under the terms of the GPL v3 (see
-#  www.gnu.org/licenses).
-#
-#  JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER
-#  EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE
-#  DISCLAIMED.
-#
-# ==============================================================================
-
-add_executable(juce_lv2_helper LV2/juce_LV2TurtleDumpProgram.cpp)
-add_executable(juce::juce_lv2_helper ALIAS juce_lv2_helper)
-target_compile_features(juce_lv2_helper PRIVATE cxx_std_14)
-set_target_properties(juce_lv2_helper PROPERTIES BUILD_WITH_INSTALL_RPATH ON)
-target_link_libraries(juce_lv2_helper PRIVATE ${CMAKE_DL_LIBS})
-install(TARGETS juce_lv2_helper EXPORT LV2_HELPER DESTINATION "bin/JUCE-${JUCE_VERSION}")
index 0e4723d28b978d47d5bd0fa179892a163d0b395c..c4ca28b39c22822df114d3a91cfa38e056bc4703 100644 (file)
   ==============================================================================\r
 */\r
 \r
+#include <cstdint>\r
+#include <cstdio>\r
+#include <cstring>\r
+#include <vector>\r
+\r
 #ifdef _WIN32\r
+ #undef UNICODE\r
+ #undef _UNICODE\r
+\r
+ #define UNICODE 1\r
+ #define _UNICODE 1\r
+\r
  #include <windows.h>\r
- HMODULE dlopen (const char* filename, int) { return LoadLibrary (filename); }\r
+ #include <tchar.h>\r
+ HMODULE dlopen (const TCHAR* filename, int) { return LoadLibrary (filename); }\r
  FARPROC dlsym (HMODULE handle, const char* name) { return GetProcAddress (handle, name); }\r
+ void printError()\r
+ {\r
+     constexpr DWORD numElements = 256;\r
+     TCHAR messageBuffer[numElements]{};\r
+\r
+     FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,\r
+                    nullptr,\r
+                    GetLastError(),\r
+                    MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT),\r
+                    messageBuffer,\r
+                    numElements - 1,\r
+                    nullptr);\r
+\r
+     _tprintf (_T ("%s"), messageBuffer);\r
+ }\r
+\r
  enum { RTLD_LAZY = 0 };\r
+\r
+ class ArgList\r
+ {\r
+ public:\r
+     ArgList (int, const char**) {}\r
+     ArgList (const ArgList&) = delete;\r
+     ArgList (ArgList&&) = delete;\r
+     ArgList& operator= (const ArgList&) = delete;\r
+     ArgList& operator= (ArgList&&) = delete;\r
+     ~ArgList() { LocalFree (argv); }\r
+\r
+     LPWSTR get (int i) const { return argv[i]; }\r
+\r
+     int size() const { return argc; }\r
+\r
+ private:\r
+     int argc = 0;\r
+     LPWSTR* argv = CommandLineToArgvW (GetCommandLineW(), &argc);\r
+ };\r
+\r
+ std::vector<char> toUTF8 (const TCHAR* str)\r
+ {\r
+     const auto numBytes = WideCharToMultiByte (CP_UTF8, 0, str, -1, nullptr, 0, nullptr, nullptr);\r
+     std::vector<char> result (numBytes);\r
+     WideCharToMultiByte (CP_UTF8, 0, str, -1, result.data(), static_cast<int> (result.size()), nullptr, nullptr);\r
+     return result;\r
+ }\r
+\r
 #else\r
  #include <dlfcn.h>\r
+ void printError() { printf ("%s\n", dlerror()); }\r
+ class ArgList\r
+ {\r
+ public:\r
+     ArgList (int argcIn, const char** argvIn) : argc (argcIn), argv (argvIn) {}\r
+     ArgList (const ArgList&) = delete;\r
+     ArgList (ArgList&&) = delete;\r
+     ArgList& operator= (const ArgList&) = delete;\r
+     ArgList& operator= (ArgList&&) = delete;\r
+     ~ArgList() = default;\r
+\r
+     const char* get (int i) const { return argv[i]; }\r
+\r
+     int size() const { return argc; }\r
+\r
+ private:\r
+     int argc = 0;\r
+     const char** argv = nullptr;\r
+ };\r
+\r
+ std::vector<char> toUTF8 (const char* str) { return std::vector<char> (str, str + std::strlen (str) + 1); }\r
 #endif\r
 \r
-#include <cstdint>\r
-\r
-// Replicating some of the LV2 header here so that we don't have to set up any\r
+// Replicating part of the LV2 header here so that we don't have to set up any\r
 // custom include paths for this file.\r
 // Normally this would be a bad idea, but the LV2 API has to keep these definitions\r
 // in order to remain backwards-compatible.\r
@@ -56,10 +131,12 @@ extern "C"
 \r
 int main (int argc, const char** argv)\r
 {\r
-    if (argc != 2)\r
+    const ArgList argList { argc, argv };\r
+\r
+    if (argList.size() != 2)\r
         return 1;\r
 \r
-    const auto* libraryPath = argv[1];\r
+    const auto* libraryPath = argList.get (1);\r
 \r
     struct RecallFeature\r
     {\r
@@ -67,12 +144,29 @@ int main (int argc, const char** argv)
     };\r
 \r
     if (auto* handle = dlopen (libraryPath, RTLD_LAZY))\r
+    {\r
         if (auto* getDescriptor = reinterpret_cast<const LV2_Descriptor* (*) (uint32_t)> (dlsym (handle, "lv2_descriptor")))\r
+        {\r
             if (auto* descriptor = getDescriptor (0))\r
+            {\r
                 if (auto* extensionData = descriptor->extension_data)\r
+                {\r
                     if (auto* recallFeature = reinterpret_cast<const RecallFeature*> (extensionData ("https://lv2-extensions.juce.com/turtle_recall")))\r
+                    {\r
                         if (auto* doRecall = recallFeature->doRecall)\r
-                            return doRecall (libraryPath);\r
+                        {\r
+                            const auto converted = toUTF8 (libraryPath);\r
+                            return doRecall (converted.data());\r
+                        }\r
+                    }\r
+                }\r
+            }\r
+        }\r
+    }\r
+    else\r
+    {\r
+        printError();\r
+    }\r
 \r
     return 1;\r
 }\r
index 6fba7a1e447890da9ff1532ace261d9921ccd02f..2c1619b6288d3ee3c782d65f1ee264c24382e670 100644 (file)
@@ -124,7 +124,14 @@ public:
     */\r
     static String getIri (const AudioProcessorParameter& param)\r
     {\r
-        return URL::addEscapeChars (LegacyAudioParameter::getParamID (&param, false), true);\r
+        const auto urlSanitised = URL::addEscapeChars (LegacyAudioParameter::getParamID (&param, false), true);\r
+        const auto ttlSanitised = lv2_shared::sanitiseStringAsTtlName (urlSanitised);\r
+\r
+        // If this is hit, the parameter ID could not be represented directly in the plugin ttl.\r
+        // We'll replace offending characters with '_'.\r
+        jassert (urlSanitised == ttlSanitised);\r
+\r
+        return ttlSanitised;\r
     }\r
 \r
     void setValueFromHost (LV2_URID urid, float value) noexcept\r
@@ -217,6 +224,11 @@ private:
             result.push_back (urid);\r
         }\r
 \r
+        // If this is hit, some parameters have duplicate IDs.\r
+        // This may be because the IDs resolve to the same string when removing characters that\r
+        // are invalid in a TTL name.\r
+        jassert (std::set<LV2_URID> (result.begin(), result.end()).size() == result.size());\r
+\r
         return result;\r
     }();\r
     const std::map<LV2_URID, size_t> uridToIndexMap = [&]\r
@@ -484,7 +496,7 @@ public:
     template<typename UnaryFunction>\r
     static void iterateAudioBuffer (AudioBuffer<float>& ab, UnaryFunction fn)\r
     {\r
-        float** sampleData = ab.getArrayOfWritePointers();\r
+        float* const* sampleData = ab.getArrayOfWritePointers();\r
 \r
         for (int c = ab.getNumChannels(); --c >= 0;)\r
             for (int s = ab.getNumSamples(); --s >= 0;)\r
@@ -505,8 +517,12 @@ public:
 \r
     void run (uint32_t numSteps)\r
     {\r
+        // If this is hit, the host is trying to process more samples than it told us to prepare\r
+        jassert (static_cast<int> (numSteps) <= processor->getBlockSize());\r
+\r
         midi.clear();\r
         playHead.invalidate();\r
+        audio.setSize (audio.getNumChannels(), static_cast<int> (numSteps), true, false, true);\r
 \r
         ports.forEachInputEvent ([&] (const LV2_Atom_Event* event)\r
         {\r
@@ -536,7 +552,7 @@ public:
         processor->setNonRealtime (ports.isFreeWheeling());\r
 \r
         for (auto i = 0, end = processor->getTotalNumInputChannels(); i < end; ++i)\r
-            audio.copyFrom (i, 0, ports.getBufferForAudioInput (i), (int) numSteps);\r
+            audio.copyFrom (i, 0, ports.getBufferForAudioInput (i), audio.getNumSamples());\r
 \r
         jassert (countNaNs (audio) == 0);\r
 \r
@@ -705,7 +721,7 @@ public:
 \r
     static std::unique_ptr<AudioProcessor> createProcessorInstance()\r
     {\r
-        std::unique_ptr<AudioProcessor> result { createPluginFilterOfType (AudioProcessor::wrapperType_LV2) };\r
+        auto result = createPluginFilterOfType (AudioProcessor::wrapperType_LV2);\r
 \r
        #if defined (JucePlugin_PreferredChannelConfigurations)\r
         constexpr short channelConfigurations[][2] { JucePlugin_PreferredChannelConfigurations };\r
@@ -797,22 +813,25 @@ struct RecallFeature
     {\r
         const ScopedJuceInitialiser_GUI scope;\r
         const auto processor = LV2PluginInstance::createProcessorInstance();\r
-        const File absolutePath { CharPointer_UTF8 { libraryPath } };\r
 \r
-        processor->enableAllBuses();\r
+        const String pathString { CharPointer_UTF8 { libraryPath } };\r
+\r
+        const auto absolutePath = File::isAbsolutePath (pathString) ? File (pathString)\r
+                                                                    : File::getCurrentWorkingDirectory().getChildFile (pathString);\r
+\r
+        const auto writers = { writeManifestTtl, writeDspTtl, writeUiTtl };\r
 \r
-        for (auto* fn : { writeManifestTtl, writeDspTtl, writeUiTtl })\r
+        const auto wroteSuccessfully = [&processor, &absolutePath] (auto* fn)\r
         {\r
             const auto result = fn (*processor, absolutePath);\r
 \r
-            if (result.wasOk())\r
-                continue;\r
+            if (result.wasOk())\r
+                std::cerr << result.getErrorMessage() << '\n';\r
 \r
-            std::cerr << result.getErrorMessage() << '\n';\r
-            return 1;\r
-        }\r
+            return result.wasOk();\r
+        };\r
 \r
-        return 0;\r
+        return std::all_of (writers.begin(), writers.end(), wroteSuccessfully) ? 0 : 1;\r
     };\r
 \r
 private:\r
@@ -821,15 +840,28 @@ private:
         return JucePlugin_LV2URI + String (uriSeparator) + "preset" + String (index + 1);\r
     }\r
 \r
-    static std::ofstream openStream (const File& libraryPath, StringRef name)\r
+    static FileOutputStream openStream (const File& libraryPath, StringRef name)\r
     {\r
-        return std::ofstream { libraryPath.getSiblingFile (name + ".ttl").getFullPathName().toRawUTF8() };\r
+        return FileOutputStream { libraryPath.getSiblingFile (name + ".ttl") };\r
+    }\r
+\r
+    static Result prepareStream (FileOutputStream& stream)\r
+    {\r
+        if (const auto result = stream.getStatus(); ! result)\r
+            return result;\r
+\r
+        stream.setPosition (0);\r
+        stream.truncate();\r
+        return Result::ok();\r
     }\r
 \r
     static Result writeManifestTtl (AudioProcessor& proc, const File& libraryPath)\r
     {\r
         auto os = openStream (libraryPath, "manifest");\r
 \r
+        if (const auto result = prepareStream (os); ! result)\r
+            return result;\r
+\r
         os << "@prefix lv2:   <http://lv2plug.in/ns/lv2core#> .\n"\r
               "@prefix rdfs:  <http://www.w3.org/2000/01/rdf-schema#> .\n"\r
               "@prefix pset:  <http://lv2plug.in/ns/ext/presets#> .\n"\r
@@ -848,7 +880,7 @@ private:
             #define JUCE_LV2_UI_KIND "CocoaUI"\r
            #elif JUCE_WINDOWS\r
             #define JUCE_LV2_UI_KIND "WindowsUI"\r
-           #elif JUCE_LINUX\r
+           #elif JUCE_LINUX || JUCE_BSD\r
             #define JUCE_LV2_UI_KIND "X11UI"\r
            #else\r
             #error "LV2 UI is unsupported on this platform"\r
@@ -961,6 +993,9 @@ private:
     {\r
         auto os = openStream (libraryPath, "dsp");\r
 \r
+        if (const auto result = prepareStream (os); ! result)\r
+            return result;\r
+\r
         os << "@prefix atom:  <http://lv2plug.in/ns/ext/atom#> .\n"\r
               "@prefix bufs:  <http://lv2plug.in/ns/ext/buf-size#> .\n"\r
               "@prefix doap:  <http://usefulinc.com/ns/doap#> .\n"\r
@@ -1298,6 +1333,9 @@ private:
 \r
         auto os = openStream (libraryPath, "ui");\r
 \r
+        if (const auto result = prepareStream (os); ! result)\r
+            return result;\r
+\r
         const auto editorInstance = rawToUniquePtr (proc.createEditor());\r
         const auto resizeFeatureString = editorInstance->isResizable() ? "ui:resize" : "ui:noUserResize";\r
 \r
@@ -1341,8 +1379,6 @@ private:
 //==============================================================================\r
 LV2_SYMBOL_EXPORT const LV2_Descriptor* lv2_descriptor (uint32_t index)\r
 {\r
-    PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_LV2;\r
-\r
     if (index != 0)\r
         return nullptr;\r
 \r
index 009707ec6b7e399c7d6ad09abee1a98039a387e9..1f13a1d8a9ac760fd500aef8c37e7b042810d242 100644 (file)
@@ -50,8 +50,6 @@ class StandaloneFilterApp  : public JUCEApplication
 public:\r
     StandaloneFilterApp()\r
     {\r
-        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_Standalone;\r
-\r
         PropertiesFile::Options options;\r
 \r
         options.applicationName     = getApplicationName();\r
index 05842cc58acd0e48fa73b52392ca351526ce5559..6a96c9beba47571652e5347b3d392c566c911aef 100644 (file)
@@ -124,7 +124,7 @@ public:
     //==============================================================================\r
     virtual void createPlugin()\r
     {\r
-        processor.reset (createPluginFilterOfType (AudioProcessor::wrapperType_Standalone));\r
+        processor = createPluginFilterOfType (AudioProcessor::wrapperType_Standalone);\r
         processor->disableNonMainBuses();\r
         processor->setRateAndBufferSizeDetails (44100, 512);\r
 \r
@@ -386,13 +386,12 @@ public:
         return false;\r
     }\r
 \r
-    Image getIAAHostIcon (int size)\r
+    Image getIAAHostIcon ([[maybe_unused]] int size)\r
     {\r
        #if JUCE_IOS && JucePlugin_Enable_IAA\r
         if (auto device = dynamic_cast<iOSAudioIODevice*> (deviceManager.getCurrentAudioDevice()))\r
             return device->getIcon (size);\r
        #else\r
-        ignoreUnused (size);\r
        #endif\r
 \r
         return {};\r
@@ -425,7 +424,7 @@ private:
 \r
         On some platforms (such as iOS 10), the expected buffer size reported in\r
         audioDeviceAboutToStart may be smaller than the blocks passed to\r
-        audioDeviceIOCallback. This can lead to out-of-bounds reads if the render\r
+        audioDeviceIOCallbackWithContext. This can lead to out-of-bounds reads if the render\r
         callback depends on additional buffers which were initialised using the\r
         smaller size.\r
 \r
@@ -448,9 +447,9 @@ private:
             inner.audioDeviceAboutToStart (device);\r
         }\r
 \r
-        void audioDeviceIOCallbackWithContext (const float** inputChannelData,\r
+        void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
                                                int numInputChannels,\r
-                                               float** outputChannelData,\r
+                                               float* const* outputChannelData,\r
                                                int numOutputChannels,\r
                                                int numSamples,\r
                                                const AudioIODeviceCallbackContext& context) override\r
@@ -600,9 +599,9 @@ private:
     };\r
 \r
     //==============================================================================\r
-    void audioDeviceIOCallbackWithContext (const float** inputChannelData,\r
+    void audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
                                            int numInputChannels,\r
-                                           float** outputChannelData,\r
+                                           float* const* outputChannelData,\r
                                            int numOutputChannels,\r
                                            int numSamples,\r
                                            const AudioIODeviceCallbackContext& context) override\r
index 47dfef29472153bd168d6722006e7223c3ac6549..e2cc0f692f3e090f812d92884d39924d56ea6bda 100644 (file)
@@ -158,10 +158,8 @@ private:
             return std::make_unique<LowLevelGraphicsSoftwareRenderer> (Image (this));\r
         }\r
 \r
-        void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, Image::BitmapData::ReadWriteMode mode) override\r
+        void initialiseBitmapData (Image::BitmapData& bitmap, int x, int y, [[maybe_unused]] Image::BitmapData::ReadWriteMode mode) override\r
         {\r
-            ignoreUnused (mode);\r
-\r
             const auto offset = (size_t) x * (size_t) pixelStride + (size_t) y * (size_t) lineStride;\r
             bitmap.data = imageData + offset;\r
             bitmap.size = (size_t) (lineStride * height) - offset;\r
@@ -294,7 +292,7 @@ class AudioProcessorUnityWrapper
 public:\r
     AudioProcessorUnityWrapper (bool isTemporary)\r
     {\r
-        pluginInstance.reset (createPluginFilterOfType (AudioProcessor::wrapperType_Unity));\r
+        pluginInstance = createPluginFilterOfType (AudioProcessor::wrapperType_Unity);\r
 \r
         if (! isTemporary && pluginInstance->hasEditor())\r
         {\r
@@ -510,9 +508,28 @@ static void onWrapperDeletion (AudioProcessorUnityWrapper* wrapperToRemove)
 }\r
 \r
 //==============================================================================\r
-namespace UnityCallbacks\r
+static UnityAudioEffectDefinition getEffectDefinition()\r
 {\r
-    static int UNITY_INTERFACE_API createCallback (UnityAudioEffectState* state)\r
+    const auto wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);\r
+    const String originalName { JucePlugin_Name };\r
+    const auto name = (! originalName.startsWithIgnoreCase ("audioplugin") ? "audioplugin_" : "") + originalName;\r
+\r
+    UnityAudioEffectDefinition result{};\r
+    name.copyToUTF8 (result.name, (size_t) numElementsInArray (result.name));\r
+\r
+    result.structSize = sizeof (UnityAudioEffectDefinition);\r
+    result.parameterStructSize = sizeof (UnityAudioParameterDefinition);\r
+\r
+    result.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;\r
+    result.pluginVersion = JucePlugin_VersionCode;\r
+\r
+    // effects must set this to 0, generators > 0\r
+    result.channels = (wrapper->getNumInputChannels() != 0 ? 0\r
+                                                           : static_cast<uint32> (wrapper->getNumOutputChannels()));\r
+\r
+    wrapper->declareParameters (result);\r
+\r
+    result.create = [] (UnityAudioEffectState* state)\r
     {\r
         auto* pluginInstance = new AudioProcessorUnityWrapper (false);\r
         pluginInstance->create (state);\r
@@ -522,9 +539,9 @@ namespace UnityCallbacks
         onWrapperCreation (pluginInstance);\r
 \r
         return 0;\r
-    }\r
+    };\r
 \r
-    static int UNITY_INTERFACE_API releaseCallback (UnityAudioEffectState* state)\r
+    result.release = [] (UnityAudioEffectState* state)\r
     {\r
         auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
         pluginInstance->release();\r
@@ -536,32 +553,57 @@ namespace UnityCallbacks
             shutdownJuce_GUI();\r
 \r
         return 0;\r
-    }\r
+    };\r
 \r
-    static int UNITY_INTERFACE_API resetCallback (UnityAudioEffectState* state)\r
+    result.reset = [] (UnityAudioEffectState* state)\r
     {\r
         auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
         pluginInstance->reset();\r
 \r
         return 0;\r
-    }\r
+    };\r
 \r
-    static int UNITY_INTERFACE_API setPositionCallback (UnityAudioEffectState* state, unsigned int pos)\r
+    result.setPosition = [] (UnityAudioEffectState* state, unsigned int pos)\r
     {\r
         ignoreUnused (state, pos);\r
+        return 0;\r
+    };\r
+\r
+    result.process = [] (UnityAudioEffectState* state,\r
+                         float* inBuffer,\r
+                         float* outBuffer,\r
+                         unsigned int bufferSize,\r
+                         int numInChannels,\r
+                         int numOutChannels)\r
+    {\r
+        auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
+\r
+        if (pluginInstance != nullptr)\r
+        {\r
+            auto isPlaying = ((state->flags & stateIsPlaying) != 0);\r
+            auto isMuted   = ((state->flags & stateIsMuted)   != 0);\r
+            auto isPaused  = ((state->flags & stateIsPaused)  != 0);\r
+\r
+            const auto bypassed = ! isPlaying || (isMuted || isPaused);\r
+            pluginInstance->process (inBuffer, outBuffer, static_cast<int> (bufferSize), numInChannels, numOutChannels, bypassed);\r
+        }\r
+        else\r
+        {\r
+            FloatVectorOperations::clear (outBuffer, static_cast<int> (bufferSize) * numOutChannels);\r
+        }\r
 \r
         return 0;\r
-    }\r
+    };\r
 \r
-    static int UNITY_INTERFACE_API setFloatParameterCallback (UnityAudioEffectState* state, int index, float value)\r
+    result.setFloatParameter = [] (UnityAudioEffectState* state, int index, float value)\r
     {\r
         auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
         pluginInstance->setParameter (index, value);\r
 \r
         return 0;\r
-    }\r
+    };\r
 \r
-    static int UNITY_INTERFACE_API getFloatParameterCallback (UnityAudioEffectState* state, int index, float* value, char* valueStr)\r
+    result.getFloatParameter = [] (UnityAudioEffectState* state, int index, float* value, char* valueStr)\r
     {\r
         auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
         *value = pluginInstance->getParameter (index);\r
@@ -569,21 +611,21 @@ namespace UnityCallbacks
         pluginInstance->getParameterString (index).copyToUTF8 (valueStr, 15);\r
 \r
         return 0;\r
-    }\r
+    };\r
 \r
-    static int UNITY_INTERFACE_API getFloatBufferCallback (UnityAudioEffectState* state, const char* name, float* buffer, int numSamples)\r
+    result.getFloatBuffer = [] (UnityAudioEffectState* state, const char* kind, float* buffer, int numSamples)\r
     {\r
         ignoreUnused (numSamples);\r
 \r
-        auto nameStr = String (name);\r
+        const StringRef kindStr { kind };\r
 \r
-        if (nameStr == "Editor")\r
+        if (kindStr == StringRef ("Editor"))\r
         {\r
             auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
 \r
             buffer[0] = pluginInstance->hasEditor() ? 1.0f : 0.0f;\r
         }\r
-        else if (nameStr == "ID")\r
+        else if (kindStr == StringRef ("ID"))\r
         {\r
             auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
 \r
@@ -598,7 +640,7 @@ namespace UnityCallbacks
 \r
             return 0;\r
         }\r
-        else if (nameStr == "Size")\r
+        else if (kindStr == StringRef ("Size"))\r
         {\r
             auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
 \r
@@ -613,87 +655,27 @@ namespace UnityCallbacks
         }\r
 \r
         return 0;\r
-    }\r
-\r
-    static int UNITY_INTERFACE_API processCallback (UnityAudioEffectState* state, float* inBuffer, float* outBuffer,\r
-                                                    unsigned int bufferSize, int numInChannels, int numOutChannels)\r
-    {\r
-        auto* pluginInstance = state->getEffectData<AudioProcessorUnityWrapper>();\r
-\r
-        if (pluginInstance != nullptr)\r
-        {\r
-            auto isPlaying = ((state->flags & stateIsPlaying) != 0);\r
-            auto isMuted   = ((state->flags & stateIsMuted)   != 0);\r
-            auto isPaused  = ((state->flags & stateIsPaused)  != 0);\r
-\r
-            const auto bypassed = ! isPlaying || (isMuted || isPaused);\r
-            pluginInstance->process (inBuffer, outBuffer, static_cast<int> (bufferSize), numInChannels, numOutChannels, bypassed);\r
-        }\r
-        else\r
-        {\r
-            FloatVectorOperations::clear (outBuffer, static_cast<int> (bufferSize) * numOutChannels);\r
-        }\r
-\r
-        return 0;\r
-    }\r
-}\r
-\r
-//==============================================================================\r
-static void declareEffect (UnityAudioEffectDefinition& definition)\r
-{\r
-    memset (&definition, 0, sizeof (definition));\r
-\r
-    std::unique_ptr<AudioProcessorUnityWrapper> wrapper = std::make_unique<AudioProcessorUnityWrapper> (true);\r
-\r
-    String name (JucePlugin_Name);\r
-    if (! name.startsWithIgnoreCase ("audioplugin"))\r
-        name = "audioplugin_" + name;\r
-\r
-    name.copyToUTF8 (definition.name, (size_t) numElementsInArray (definition.name));\r
-\r
-    definition.structSize = sizeof (UnityAudioEffectDefinition);\r
-    definition.parameterStructSize = sizeof (UnityAudioParameterDefinition);\r
-\r
-    definition.apiVersion = UNITY_AUDIO_PLUGIN_API_VERSION;\r
-    definition.pluginVersion = JucePlugin_VersionCode;\r
+    };\r
 \r
-    // effects must set this to 0, generators > 0\r
-    definition.channels = (wrapper->getNumInputChannels() != 0 ? 0\r
-                                                               : static_cast<uint32> (wrapper->getNumOutputChannels()));\r
-\r
-    wrapper->declareParameters (definition);\r
-\r
-    definition.create            = UnityCallbacks::createCallback;\r
-    definition.release           = UnityCallbacks::releaseCallback;\r
-    definition.reset             = UnityCallbacks::resetCallback;\r
-    definition.setPosition       = UnityCallbacks::setPositionCallback;\r
-    definition.process           = UnityCallbacks::processCallback;\r
-    definition.setFloatParameter = UnityCallbacks::setFloatParameterCallback;\r
-    definition.getFloatParameter = UnityCallbacks::getFloatParameterCallback;\r
-    definition.getFloatBuffer    = UnityCallbacks::getFloatBufferCallback;\r
+    return result;\r
 }\r
 \r
 } // namespace juce\r
 \r
+// From reading the example code, it seems that the triple indirection indicates\r
+// an out-value of an array of pointers. That is, after calling this function, definitionsPtr\r
+// should point to a pre-existing/static array of pointer-to-effect-definition.\r
 UNITY_INTERFACE_EXPORT int UNITY_INTERFACE_API UnityGetAudioEffectDefinitions (UnityAudioEffectDefinition*** definitionsPtr)\r
 {\r
     if (juce::getWrapperMap().size() == 0)\r
         juce::initialiseJuce_GUI();\r
 \r
-    static bool hasInitialised = false;\r
-\r
-    if (! hasInitialised)\r
-    {\r
-        juce::PluginHostType::jucePlugInClientCurrentWrapperType = juce::AudioProcessor::wrapperType_Unity;\r
-        juce::juce_createUnityPeerFn = juce::createUnityPeer;\r
-\r
-        hasInitialised = true;\r
-    }\r
-\r
-    auto* definition = new UnityAudioEffectDefinition();\r
-    juce::declareEffect (*definition);\r
+    static std::once_flag flag;\r
+    std::call_once (flag, [] { juce::juce_createUnityPeerFn = juce::createUnityPeer; });\r
 \r
-    *definitionsPtr = &definition;\r
+    static auto definition = juce::getEffectDefinition();\r
+    static UnityAudioEffectDefinition* definitions[] { &definition };\r
+    *definitionsPtr = definitions;\r
 \r
     return 1;\r
 }\r
index 1127dd2524fc11347822c65194b45affa40aa57a..55226c66a64912e6eb395dba989d89b995c541c9 100644 (file)
@@ -68,6 +68,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996 4100)
 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wconversion",\r
                                      "-Wshadow",\r
                                      "-Wdeprecated-register",\r
+                                     "-Wdeprecated-declarations",\r
                                      "-Wunused-parameter",\r
                                      "-Wdeprecated-writable-strings",\r
                                      "-Wnon-virtual-dtor",\r
@@ -961,14 +962,12 @@ public:
                               , public Timer\r
                              #endif\r
     {\r
-        EditorCompWrapper (JuceVSTWrapper& w, AudioProcessorEditor& editor, float initialScale)\r
+        EditorCompWrapper (JuceVSTWrapper& w, AudioProcessorEditor& editor, [[maybe_unused]] float initialScale)\r
             : wrapper (w)\r
         {\r
             editor.setOpaque (true);\r
            #if ! JUCE_MAC\r
             editor.setScaleFactor (initialScale);\r
-           #else\r
-            ignoreUnused (initialScale);\r
            #endif\r
             addAndMakeVisible (editor);\r
 \r
@@ -1018,7 +1017,7 @@ public:
              // before that happens.\r
              X11Symbols::getInstance()->xFlush (display);\r
             #elif JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
-             checkHostWindowScaleFactor();\r
+             checkHostWindowScaleFactor (true);\r
              startTimer (500);\r
             #endif\r
            #elif JUCE_MAC\r
@@ -1222,12 +1221,12 @@ public:
         }\r
 \r
         #if JUCE_WIN_PER_MONITOR_DPI_AWARE\r
-         void checkHostWindowScaleFactor()\r
+         void checkHostWindowScaleFactor (bool force = false)\r
          {\r
              auto hostWindowScale = (float) getScaleFactorForWindow ((HostWindowType) hostWindow);\r
 \r
-             if (hostWindowScale > 0.0f && ! approximatelyEqual (hostWindowScale, wrapper.editorScaleFactor))\r
-                 wrapper.handleSetContentScaleFactor (hostWindowScale);\r
+             if (force || (hostWindowScale > 0.0f && ! approximatelyEqual (hostWindowScale, wrapper.editorScaleFactor)))\r
+                 wrapper.handleSetContentScaleFactor (hostWindowScale, force);\r
          }\r
 \r
          void timerCallback() override\r
@@ -1713,13 +1712,12 @@ private:
         return 0;\r
     }\r
 \r
-    pointer_sized_int handlePreAudioProcessingEvents (VstOpCodeArguments args)\r
+    pointer_sized_int handlePreAudioProcessingEvents ([[maybe_unused]] VstOpCodeArguments args)\r
     {\r
        #if JucePlugin_WantsMidiInput || JucePlugin_IsMidiEffect\r
         VSTMidiEventList::addEventsToMidiBuffer ((Vst2::VstEvents*) args.ptr, midiEvents);\r
         return 1;\r
        #else\r
-        ignoreUnused (args);\r
         return 0;\r
        #endif\r
     }\r
@@ -1972,13 +1970,13 @@ private:
         if (pluginHasSidechainsOrAuxs() || processor->isMidiEffect())\r
             return false;\r
 \r
-        auto inputLayout  = processor->getChannelLayoutOfBus (true,  0);\r
-        auto outputLayout = processor->getChannelLayoutOfBus (false,  0);\r
+        auto inputLayout  = processor->getChannelLayoutOfBus (true, 0);\r
+        auto outputLayout = processor->getChannelLayoutOfBus (false, 0);\r
 \r
-        auto speakerBaseSize = sizeof (Vst2::VstSpeakerArrangement) - (sizeof (Vst2::VstSpeakerProperties) * 8);\r
+        const auto speakerBaseSize = offsetof (Vst2::VstSpeakerArrangement, speakers);\r
 \r
-        cachedInArrangement .malloc (speakerBaseSize + (static_cast<std::size_t> (inputLayout. size()) * sizeof (Vst2::VstSpeakerArrangement)), 1);\r
-        cachedOutArrangement.malloc (speakerBaseSize + (static_cast<std::size_t> (outputLayout.size()) * sizeof (Vst2::VstSpeakerArrangement)), 1);\r
+        cachedInArrangement .malloc (speakerBaseSize + (static_cast<std::size_t> (inputLayout. size()) * sizeof (Vst2::VstSpeakerProperties)), 1);\r
+        cachedOutArrangement.malloc (speakerBaseSize + (static_cast<std::size_t> (outputLayout.size()) * sizeof (Vst2::VstSpeakerProperties)), 1);\r
 \r
         *pluginInput  = cachedInArrangement. getData();\r
         *pluginOutput = cachedOutArrangement.getData();\r
@@ -2012,7 +2010,7 @@ private:
         return 0;\r
     }\r
 \r
-    pointer_sized_int handleSetContentScaleFactor (float scale)\r
+    pointer_sized_int handleSetContentScaleFactor ([[maybe_unused]] float scale, [[maybe_unused]] bool force = false)\r
     {\r
         checkWhetherMessageThreadIsCorrect();\r
        #if JUCE_LINUX || JUCE_BSD\r
@@ -2022,16 +2020,13 @@ private:
        #endif\r
 \r
        #if ! JUCE_MAC\r
-        if (! approximatelyEqual (scale, editorScaleFactor))\r
+        if (force || ! approximatelyEqual (scale, editorScaleFactor))\r
         {\r
             editorScaleFactor = scale;\r
 \r
             if (editorComp != nullptr)\r
                 editorComp->setContentScaleFactor (editorScaleFactor);\r
         }\r
-\r
-       #else\r
-        ignoreUnused (scale);\r
        #endif\r
 \r
         return 1;\r
@@ -2198,8 +2193,6 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes")
     JUCE_EXPORTED_FUNCTION Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster);\r
     JUCE_EXPORTED_FUNCTION Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster)\r
     {\r
-        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;\r
-\r
         initialiseMacVST();\r
         return pluginEntryPoint (audioMaster);\r
     }\r
@@ -2207,8 +2200,6 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes")
     JUCE_EXPORTED_FUNCTION Vst2::AEffect* main_macho (Vst2::audioMasterCallback audioMaster);\r
     JUCE_EXPORTED_FUNCTION Vst2::AEffect* main_macho (Vst2::audioMasterCallback audioMaster)\r
     {\r
-        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;\r
-\r
         initialiseMacVST();\r
         return pluginEntryPoint (audioMaster);\r
     }\r
@@ -2220,16 +2211,12 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes")
     JUCE_EXPORTED_FUNCTION Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster);\r
     JUCE_EXPORTED_FUNCTION Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster)\r
     {\r
-        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;\r
-\r
         return pluginEntryPoint (audioMaster);\r
     }\r
 \r
     JUCE_EXPORTED_FUNCTION Vst2::AEffect* main_plugin (Vst2::audioMasterCallback audioMaster) asm ("main");\r
     JUCE_EXPORTED_FUNCTION Vst2::AEffect* main_plugin (Vst2::audioMasterCallback audioMaster)\r
     {\r
-        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;\r
-\r
         return VSTPluginMain (audioMaster);\r
     }\r
 \r
@@ -2243,16 +2230,12 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wmissing-prototypes")
 \r
     extern "C" __declspec (dllexport) Vst2::AEffect* VSTPluginMain (Vst2::audioMasterCallback audioMaster)\r
     {\r
-        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;\r
-\r
         return pluginEntryPoint (audioMaster);\r
     }\r
 \r
    #if ! defined (JUCE_64BIT) && JUCE_MSVC // (can't compile this on win64, but it's not needed anyway with VST2.4)\r
     extern "C" __declspec (dllexport) int main (Vst2::audioMasterCallback audioMaster)\r
     {\r
-        PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST;\r
-\r
         return (int) pluginEntryPoint (audioMaster);\r
     }\r
    #endif\r
index 8e3fab41244299644865be5394bc5ff4802ed14f..2c13881a5aff706625ebb1ac4d9315621167238e 100644 (file)
@@ -80,7 +80,7 @@ void initialiseMacVST()
 }\r
 \r
 JUCE_API void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView);\r
-void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, bool isNSView)\r
+void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView, [[maybe_unused]] bool isNSView)\r
 {\r
     JUCE_AUTORELEASEPOOL\r
     {\r
@@ -161,7 +161,6 @@ void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView,
         }\r
        #endif\r
 \r
-        ignoreUnused (isNSView);\r
         NSView* parentView = [(NSView*) parentWindowOrView retain];\r
 \r
        #if JucePlugin_EditorRequiresKeyboardFocus\r
@@ -183,7 +182,7 @@ void* attachComponentToWindowRefVST (Component* comp, void* parentWindowOrView,
 }\r
 \r
 JUCE_API void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView);\r
-void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSView)\r
+void detachComponentFromWindowRefVST (Component* comp, void* window, [[maybe_unused]] bool isNSView)\r
 {\r
     JUCE_AUTORELEASEPOOL\r
     {\r
@@ -232,14 +231,13 @@ void detachComponentFromWindowRefVST (Component* comp, void* window, bool isNSVi
         }\r
        #endif\r
 \r
-        ignoreUnused (isNSView);\r
         comp->removeFromDesktop();\r
         [(id) window release];\r
     }\r
 }\r
 \r
 JUCE_API void setNativeHostWindowSizeVST (void* window, Component* component, int newWidth, int newHeight, bool isNSView);\r
-void setNativeHostWindowSizeVST (void* window, Component* component, int newWidth, int newHeight, bool isNSView)\r
+void setNativeHostWindowSizeVST (void* window, Component* component, int newWidth, int newHeight, [[maybe_unused]] bool isNSView)\r
 {\r
     JUCE_AUTORELEASEPOOL\r
     {\r
@@ -260,8 +258,6 @@ void setNativeHostWindowSizeVST (void* window, Component* component, int newWidt
         }\r
        #endif\r
 \r
-        ignoreUnused (isNSView);\r
-\r
         if (NSView* hostView = (NSView*) window)\r
         {\r
             const int dx = newWidth  - component->getWidth();\r
@@ -277,10 +273,10 @@ void setNativeHostWindowSizeVST (void* window, Component* component, int newWidt
 }\r
 \r
 JUCE_API void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView);\r
-void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView)\r
+void checkWindowVisibilityVST ([[maybe_unused]] void* window,\r
+                               [[maybe_unused]] Component* comp,\r
+                               [[maybe_unused]] bool isNSView)\r
 {\r
-    ignoreUnused (window, comp, isNSView);\r
-\r
    #if ! JUCE_64BIT\r
     if (! isNSView)\r
         comp->setVisible ([((NSWindow*) window) isVisible]);\r
@@ -288,7 +284,7 @@ void checkWindowVisibilityVST (void* window, Component* comp, bool isNSView)
 }\r
 \r
 JUCE_API bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView);\r
-bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView)\r
+bool forwardCurrentKeyEventToHostVST ([[maybe_unused]] Component* comp, [[maybe_unused]] bool isNSView)\r
 {\r
    #if ! JUCE_64BIT\r
     if (! isNSView)\r
@@ -300,7 +296,6 @@ bool forwardCurrentKeyEventToHostVST (Component* comp, bool isNSView)
     }\r
    #endif\r
 \r
-    ignoreUnused (comp, isNSView);\r
     return false;\r
 }\r
 \r
index b80ae5a5bbd09a02e1dbd4117f614363ff47ef86..da79dcc63ff8b069ac4462a26ea0abe4c69c02c4 100644 (file)
@@ -431,9 +431,11 @@ public:
         {\r
             info.id             = Vst::kRootUnitId;\r
             info.parentUnitId   = Vst::kNoParentUnitId;\r
-            info.programListId  = Vst::kNoProgramListId;\r
+            info.programListId  = getProgramListCount() > 0\r
+                                ? static_cast<Vst::ProgramListID> (programParamID)\r
+                                : Vst::kNoProgramListId;\r
 \r
-            toString128 (info.name, TRANS("Root Unit"));\r
+            toString128 (info.name, TRANS ("Root Unit"));\r
 \r
             return kResultTrue;\r
         }\r
@@ -467,7 +469,7 @@ public:
             info.id = static_cast<Vst::ProgramListID> (programParamID);\r
             info.programCount = static_cast<Steinberg::int32> (audioProcessor->getNumPrograms());\r
 \r
-            toString128 (info.name, TRANS("Factory Presets"));\r
+            toString128 (info.name, TRANS ("Factory Presets"));\r
 \r
             return kResultTrue;\r
         }\r
@@ -500,8 +502,8 @@ public:
 \r
     tresult PLUGIN_API getUnitByBus (Vst::MediaType, Vst::BusDirection, Steinberg::int32, Steinberg::int32, Vst::UnitID& unitId) override\r
     {\r
-        zerostruct (unitId);\r
-        return kNotImplemented;\r
+        unitId = Vst::kRootUnitId;\r
+        return kResultOk;\r
     }\r
 \r
     //==============================================================================\r
@@ -1073,14 +1075,15 @@ public:
     }\r
 \r
     //==============================================================================\r
-    tresult PLUGIN_API getMidiControllerAssignment (Steinberg::int32 /*busIndex*/, Steinberg::int16 channel,\r
-                                                    Vst::CtrlNumber midiControllerNumber, Vst::ParamID& resultID) override\r
+    tresult PLUGIN_API getMidiControllerAssignment ([[maybe_unused]] Steinberg::int32 busIndex,\r
+                                                    [[maybe_unused]] Steinberg::int16 channel,\r
+                                                    [[maybe_unused]] Vst::CtrlNumber midiControllerNumber,\r
+                                                    [[maybe_unused]] Vst::ParamID& resultID) override\r
     {\r
        #if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS\r
         resultID = midiControllerToParameter[channel][midiControllerNumber];\r
         return kResultTrue; // Returning false makes some hosts stop asking for further MIDI Controller Assignments\r
        #else\r
-        ignoreUnused (channel, midiControllerNumber, resultID);\r
         return kResultFalse;\r
        #endif\r
     }\r
@@ -1127,18 +1130,18 @@ public:
         if (audioProcessor != nullptr)\r
             return audioProcessor->getUnitInfo (unitIndex, info);\r
 \r
+        jassertfalse;\r
         if (unitIndex == 0)\r
         {\r
             info.id             = Vst::kRootUnitId;\r
             info.parentUnitId   = Vst::kNoParentUnitId;\r
             info.programListId  = Vst::kNoProgramListId;\r
 \r
-            toString128 (info.name, TRANS("Root Unit"));\r
+            toString128 (info.name, TRANS ("Root Unit"));\r
 \r
             return kResultTrue;\r
         }\r
 \r
-        jassertfalse;\r
         zerostruct (info);\r
         return kResultFalse;\r
     }\r
@@ -1734,9 +1737,6 @@ private:
            #if JUCE_MAC\r
             if (getHostType().type == PluginHostType::SteinbergCubase10)\r
                 cubase10Workaround.reset (new Cubase10WindowResizeWorkaround (*this));\r
-           #else\r
-            if (! approximatelyEqual (editorScaleFactor, ec.lastScaleFactorReceived))\r
-                setContentScaleFactor (ec.lastScaleFactorReceived);\r
            #endif\r
         }\r
 \r
@@ -1784,12 +1784,24 @@ private:
             createContentWrapperComponentIfNeeded();\r
 \r
            #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD\r
+            // If the plugin was last opened at a particular scale, try to reapply that scale here.\r
+            // Note that we do this during attach(), rather than in JuceVST3Editor(). During the\r
+            // constructor, we don't have a host plugFrame, so\r
+            // ContentWrapperComponent::resizeHostWindow() won't do anything, and the content\r
+            // wrapper component will be left at the wrong size.\r
+            applyScaleFactor (StoredScaleFactor{}.withInternal (owner->lastScaleFactorReceived));\r
+\r
+            // Check the host scale factor *before* calling addToDesktop, so that the initial\r
+            // window size during addToDesktop is correct for the current platform scale factor.\r
+            #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
+             component->checkHostWindowScaleFactor();\r
+            #endif\r
+\r
             component->setOpaque (true);\r
             component->addToDesktop (0, (void*) systemWindow);\r
             component->setVisible (true);\r
 \r
             #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
-             component->checkHostWindowScaleFactor();\r
              component->startTimer (500);\r
             #endif\r
 \r
@@ -1980,39 +1992,31 @@ private:
             return kResultFalse;\r
         }\r
 \r
-        tresult PLUGIN_API setContentScaleFactor (Steinberg::IPlugViewContentScaleSupport::ScaleFactor factor) override\r
+        tresult PLUGIN_API setContentScaleFactor ([[maybe_unused]] const Steinberg::IPlugViewContentScaleSupport::ScaleFactor factor) override\r
         {\r
            #if ! JUCE_MAC\r
-            if (! approximatelyEqual ((float) factor, editorScaleFactor))\r
+            const auto scaleToApply = [&]\r
             {\r
                #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
                 // Cubase 10 only sends integer scale factors, so correct this for fractional scales\r
-                if (getHostType().type == PluginHostType::SteinbergCubase10)\r
-                {\r
-                    auto hostWindowScale = (Steinberg::IPlugViewContentScaleSupport::ScaleFactor) getScaleFactorForWindow ((HWND) systemWindow);\r
+                if (getHostType().type != PluginHostType::SteinbergCubase10)\r
+                    return factor;\r
 \r
-                    if (hostWindowScale > 0.0 && ! approximatelyEqual (factor, hostWindowScale))\r
-                        factor = hostWindowScale;\r
-                }\r
-               #endif\r
+                const auto hostWindowScale = (Steinberg::IPlugViewContentScaleSupport::ScaleFactor) getScaleFactorForWindow (static_cast<HWND> (systemWindow));\r
 \r
-                editorScaleFactor = (float) factor;\r
+                if (hostWindowScale <= 0.0 || approximatelyEqual (factor, hostWindowScale))\r
+                    return factor;\r
 \r
-                if (owner != nullptr)\r
-                    owner->lastScaleFactorReceived = editorScaleFactor;\r
+                return hostWindowScale;\r
+               #else\r
+                return factor;\r
+               #endif\r
+            }();\r
 \r
-                if (component != nullptr)\r
-                {\r
-                   #if JUCE_LINUX || JUCE_BSD\r
-                    const MessageManagerLock mmLock;\r
-                   #endif\r
-                    component->setEditorScaleFactor (editorScaleFactor);\r
-                }\r
-            }\r
+            applyScaleFactor (scaleFactor.withHost (scaleToApply));\r
 \r
             return kResultTrue;\r
            #else\r
-            ignoreUnused (factor);\r
             return kResultFalse;\r
            #endif\r
         }\r
@@ -2093,7 +2097,7 @@ private:
 \r
                     pluginEditor->setHostContext (editorHostContext.get());\r
                    #if ! JUCE_MAC\r
-                    pluginEditor->setScaleFactor (owner.editorScaleFactor);\r
+                    pluginEditor->setScaleFactor (owner.scaleFactor.get());\r
                    #endif\r
 \r
                     addAndMakeVisible (pluginEditor.get());\r
@@ -2224,10 +2228,10 @@ private:
            #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
             void checkHostWindowScaleFactor()\r
             {\r
-                auto hostWindowScale = (float) getScaleFactorForWindow ((HWND) owner.systemWindow);\r
+                const auto estimatedScale = (float) getScaleFactorForWindow (static_cast<HWND> (owner.systemWindow));\r
 \r
-                if (hostWindowScale > 0.0 && ! approximatelyEqual (hostWindowScale, owner.editorScaleFactor))\r
-                    owner.setContentScaleFactor (hostWindowScale);\r
+                if (estimatedScale > 0.0)\r
+                    owner.applyScaleFactor (owner.scaleFactor.withInternal (estimatedScale));\r
             }\r
 \r
             void timerCallback() override\r
@@ -2311,7 +2315,38 @@ private:
 \r
         std::unique_ptr<Cubase10WindowResizeWorkaround> cubase10Workaround;\r
        #else\r
-        float editorScaleFactor = 1.0f;\r
+        class StoredScaleFactor\r
+        {\r
+        public:\r
+            StoredScaleFactor withHost     (float x) const { return withMember (*this, &StoredScaleFactor::host,     x); }\r
+            StoredScaleFactor withInternal (float x) const { return withMember (*this, &StoredScaleFactor::internal, x); }\r
+            float get() const { return host.value_or (internal); }\r
+\r
+        private:\r
+            std::optional<float> host;\r
+            float internal = 1.0f;\r
+        };\r
+\r
+        void applyScaleFactor (const StoredScaleFactor newFactor)\r
+        {\r
+            const auto previous = std::exchange (scaleFactor, newFactor).get();\r
+\r
+            if (previous == scaleFactor.get())\r
+                return;\r
+\r
+            if (owner != nullptr)\r
+                owner->lastScaleFactorReceived = scaleFactor.get();\r
+\r
+            if (component != nullptr)\r
+            {\r
+               #if JUCE_LINUX || JUCE_BSD\r
+                const MessageManagerLock mmLock;\r
+               #endif\r
+                component->setEditorScaleFactor (scaleFactor.get());\r
+            }\r
+        }\r
+\r
+        StoredScaleFactor scaleFactor;\r
 \r
         #if JUCE_WINDOWS\r
          WindowsHooks hooks;\r
@@ -2385,16 +2420,15 @@ class JuceVST3Component : public Vst::IComponent,
 {\r
 public:\r
     JuceVST3Component (Vst::IHostApplication* h)\r
-        : pluginInstance (createPluginFilterOfType (AudioProcessor::wrapperType_VST3)),\r
+        : pluginInstance (createPluginFilterOfType (AudioProcessor::wrapperType_VST3).release()),\r
           host (h)\r
     {\r
         inParameterChangedCallback = false;\r
 \r
        #ifdef JucePlugin_PreferredChannelConfigurations\r
         short configs[][2] = { JucePlugin_PreferredChannelConfigurations };\r
-        const int numConfigs = numElementsInArray (configs);\r
+        [[maybe_unused]] const int numConfigs = numElementsInArray (configs);\r
 \r
-        ignoreUnused (numConfigs);\r
         jassert (numConfigs > 0 && (configs[0][0] > 0 || configs[0][1] > 0));\r
 \r
         pluginInstance->setPlayConfigDetails (configs[0][0], configs[0][1], 44100.0, 1024);\r
@@ -2517,27 +2551,32 @@ public:
     //==============================================================================\r
     tresult PLUGIN_API setActive (TBool state) override\r
     {\r
-        active = (state != 0);\r
+        const auto willBeActive = (state != 0);\r
 \r
-        if (! state)\r
-        {\r
-            getPluginInstance().releaseResources();\r
-        }\r
-        else\r
-        {\r
-            auto sampleRate = getPluginInstance().getSampleRate();\r
-            auto bufferSize = getPluginInstance().getBlockSize();\r
+        active = false;\r
+        // Some hosts may call setBusArrangements in response to calls made during prepareToPlay\r
+        // or releaseResources. Specifically, Wavelab 11.1 calls setBusArrangements in the same\r
+        // call stack when the AudioProcessor calls setLatencySamples inside prepareToPlay.\r
+        // In order for setBusArrangements to return successfully, the plugin must not be activated\r
+        // until after prepareToPlay has completely finished.\r
+        const ScopeGuard scope { [&] { active = willBeActive; } };\r
 \r
-            sampleRate = processSetup.sampleRate > 0.0\r
-                            ? processSetup.sampleRate\r
-                            : sampleRate;\r
+        if (willBeActive)\r
+        {\r
+            const auto sampleRate = processSetup.sampleRate > 0.0\r
+                                  ? processSetup.sampleRate\r
+                                  : getPluginInstance().getSampleRate();\r
 \r
-            bufferSize = processSetup.maxSamplesPerBlock > 0\r
-                            ? (int) processSetup.maxSamplesPerBlock\r
-                            : bufferSize;\r
+            const auto bufferSize = processSetup.maxSamplesPerBlock > 0\r
+                                  ? (int) processSetup.maxSamplesPerBlock\r
+                                  : getPluginInstance().getBlockSize();\r
 \r
             preparePlugin (sampleRate, bufferSize, CallPrepareToPlay::yes);\r
         }\r
+        else\r
+        {\r
+            getPluginInstance().releaseResources();\r
+        }\r
 \r
         return kResultOk;\r
     }\r
@@ -3246,25 +3285,54 @@ public:
         if (numIns > numInputBuses || numOuts > numOutputBuses)\r
             return false;\r
 \r
-        auto requested = pluginInstance->getBusesLayout();\r
+        // see the following documentation to understand the correct way to react to this callback\r
+        // https://steinbergmedia.github.io/vst3_doc/vstinterfaces/classSteinberg_1_1Vst_1_1IAudioProcessor.html#ad3bc7bac3fd3b194122669be2a1ecc42\r
 \r
-        for (int i = 0; i < numIns; ++i)\r
-            requested.getChannelSet (true,  i) = getChannelSetForSpeakerArrangement (inputs[i]);\r
+        const auto requestedLayout = [&]\r
+        {\r
+            auto result = pluginInstance->getBusesLayout();\r
 \r
-        for (int i = 0; i < numOuts; ++i)\r
-            requested.getChannelSet (false, i) = getChannelSetForSpeakerArrangement (outputs[i]);\r
+            for (int i = 0; i < numIns; ++i)\r
+                result.getChannelSet (true,  i) = getChannelSetForSpeakerArrangement (inputs[i]);\r
+\r
+            for (int i = 0; i < numOuts; ++i)\r
+                result.getChannelSet (false, i) = getChannelSetForSpeakerArrangement (outputs[i]);\r
+\r
+            return result;\r
+        }();\r
 \r
        #ifdef JucePlugin_PreferredChannelConfigurations\r
         short configs[][2] = { JucePlugin_PreferredChannelConfigurations };\r
-        if (! AudioProcessor::containsLayout (requested, configs))\r
+        if (! AudioProcessor::containsLayout (requestedLayout, configs))\r
             return kResultFalse;\r
        #endif\r
 \r
-        if (! pluginInstance->setBusesLayoutWithoutEnabling (requested))\r
-            return kResultFalse;\r
+        if (pluginInstance->checkBusesLayoutSupported (requestedLayout))\r
+        {\r
+            if (! pluginInstance->setBusesLayoutWithoutEnabling (requestedLayout))\r
+                return kResultFalse;\r
 \r
-        bufferMapper.updateFromProcessor (*pluginInstance);\r
-        return kResultTrue;\r
+            bufferMapper.updateFromProcessor (*pluginInstance);\r
+            return kResultTrue;\r
+        }\r
+\r
+        // apply layout changes in reverse order as Steinberg says we should prioritize main buses\r
+        const auto nextBest = [this, numInputBuses, numOutputBuses, &requestedLayout]\r
+        {\r
+            auto layout = pluginInstance->getBusesLayout();\r
+\r
+            for (auto busIdx = jmax (numInputBuses, numOutputBuses) - 1; busIdx >= 0; --busIdx)\r
+                for (const auto isInput : { true, false })\r
+                    if (auto* bus = pluginInstance->getBus (isInput, busIdx))\r
+                        bus->isLayoutSupported (requestedLayout.getChannelSet (isInput, busIdx), &layout);\r
+\r
+            return layout;\r
+        }();\r
+\r
+        if (pluginInstance->setBusesLayoutWithoutEnabling (nextBest))\r
+            bufferMapper.updateFromProcessor (*pluginInstance);\r
+\r
+        return kResultFalse;\r
     }\r
 \r
     tresult PLUGIN_API getBusArrangement (Vst::BusDirection dir, Steinberg::int32 index, Vst::SpeakerArrangement& arr) override\r
@@ -3337,31 +3405,45 @@ public:
     {\r
         jassert (pluginInstance != nullptr);\r
 \r
-        auto numParamsChanged = paramChanges.getParameterCount();\r
+        struct ParamChangeInfo\r
+        {\r
+            Steinberg::int32 offsetSamples = 0;\r
+            double value = 0.0;\r
+        };\r
+\r
+        const auto getPointFromQueue = [] (Steinberg::Vst::IParamValueQueue* queue, Steinberg::int32 index)\r
+        {\r
+            ParamChangeInfo result;\r
+            return queue->getPoint (index, result.offsetSamples, result.value) == kResultTrue\r
+                   ? makeOptional (result)\r
+                   : nullopt;\r
+        };\r
+\r
+        const auto numParamsChanged = paramChanges.getParameterCount();\r
 \r
         for (Steinberg::int32 i = 0; i < numParamsChanged; ++i)\r
         {\r
             if (auto* paramQueue = paramChanges.getParameterData (i))\r
             {\r
-                auto numPoints = paramQueue->getPointCount();\r
-\r
-                Steinberg::int32 offsetSamples = 0;\r
-                double value = 0.0;\r
+                const auto vstParamID = paramQueue->getParameterId();\r
+                const auto numPoints  = paramQueue->getPointCount();\r
 \r
-                if (paramQueue->getPoint (numPoints - 1, offsetSamples, value) == kResultTrue)\r
+               #if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS\r
+                if (juceVST3EditController != nullptr && juceVST3EditController->isMidiControllerParamID (vstParamID))\r
                 {\r
-                    auto vstParamID = paramQueue->getParameterId();\r
-\r
-                   #if JUCE_VST3_EMULATE_MIDI_CC_WITH_PARAMETERS\r
-                    if (juceVST3EditController != nullptr && juceVST3EditController->isMidiControllerParamID (vstParamID))\r
-                        addParameterChangeToMidiBuffer (offsetSamples, vstParamID, value);\r
-                    else\r
-                   #endif\r
+                    for (Steinberg::int32 point = 0; point < numPoints; ++point)\r
                     {\r
-                        if (auto* param = comPluginInstance->getParamForVSTParamID (vstParamID))\r
-                            setValueAndNotifyIfChanged (*param, (float) value);\r
+                        if (const auto change = getPointFromQueue (paramQueue, point))\r
+                            addParameterChangeToMidiBuffer (change->offsetSamples, vstParamID, change->value);\r
                     }\r
                 }\r
+                else\r
+               #endif\r
+                if (const auto change = getPointFromQueue (paramQueue, numPoints - 1))\r
+                {\r
+                    if (auto* param = comPluginInstance->getParamForVSTParamID (vstParamID))\r
+                        setValueAndNotifyIfChanged (*param, (float) change->value);\r
+                }\r
             }\r
         }\r
     }\r
@@ -4086,8 +4168,6 @@ using namespace juce;
 // The VST3 plugin entry point.\r
 extern "C" SMTG_EXPORT_SYMBOL IPluginFactory* PLUGIN_API GetPluginFactory()\r
 {\r
-    PluginHostType::jucePlugInClientCurrentWrapperType = AudioProcessor::wrapperType_VST3;\r
-\r
    #if (JUCE_MSVC || (JUCE_WINDOWS && JUCE_CLANG)) && JUCE_32BIT\r
     // Cunning trick to force this function to be exported. Life's too short to\r
     // faff around creating .def files for this kind of thing.\r
index 39fd87e8e23f03ccf16fb3e9ff97a99a7b6f39b0..ae55ffd3e601e903a32a995382f61ad8b03c74c5 100644 (file)
 \r
   ID:                 juce_audio_plugin_client\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE audio plugin wrapper classes\r
   description:        Classes for building VST, VST3, AU, AUv3 and AAX plugins.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_audio_processors\r
 \r
diff --git a/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r b/modules/juce_audio_plugin_client/juce_audio_plugin_client_AU.r
deleted file mode 100644 (file)
index 06eb4cd..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-/*\r
-  ==============================================================================\r
-\r
-   This file is part of the JUCE library.\r
-   Copyright (c) 2022 - Raw Material Software Limited\r
-\r
-   JUCE is an open source library subject to commercial or open-source\r
-   licensing.\r
-\r
-   By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
-   Agreement and JUCE Privacy Policy.\r
-\r
-   End User License Agreement: www.juce.com/juce-7-licence\r
-   Privacy Policy: www.juce.com/juce-privacy-policy\r
-\r
-   Or: You may also use this code under the terms of the GPL v3 (see\r
-   www.gnu.org/licenses).\r
-\r
-   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
-   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
-   DISCLAIMED.\r
-\r
-  ==============================================================================\r
-*/\r
-\r
-#define UseExtendedThingResource 1\r
-#include <AudioUnit.r>\r
-\r
-//==============================================================================\r
-/*  The JucePluginDefines file should be a file in your project, containing info to describe the\r
-    plugin's name, type, etc. The Projucer will generate this file automatically for you.\r
-\r
-    You may need to adjust the include path of your project to make sure it can be\r
-    found by this include statement. (Don't hack this file to change the include path)\r
-*/\r
-#include "JucePluginDefines.h"\r
-\r
-\r
-//==============================================================================\r
-// component resources for Audio Unit\r
-#define RES_ID          1000\r
-#define COMP_TYPE       JucePlugin_AUMainType\r
-#define COMP_SUBTYPE    JucePlugin_AUSubType\r
-#define COMP_MANUF      JucePlugin_AUManufacturerCode\r
-#define VERSION         JucePlugin_VersionCode\r
-#define NAME            JucePlugin_Manufacturer ": " JucePlugin_Name\r
-#define DESCRIPTION     JucePlugin_Desc\r
-#define ENTRY_POINT     JucePlugin_AUExportPrefixQuoted "Entry"\r
-\r
-#include "AUResources.r"\r
index d36d18b2a1809d632be6d1c053b8c78752c26739..ed10cded95f4f38ce307211e6c076f0f832b85c3 100644 (file)
@@ -60,21 +60,42 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wparentheses",
  #define verify_noerr(errorCode)  __Verify_noErr(errorCode)\r
 #endif\r
 \r
-#include "AU/CoreAudioUtilityClasses/AUBase.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUBuffer.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUDispatch.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUInputElement.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUMIDIBase.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUOutputBase.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUOutputElement.cpp"\r
-#include "AU/CoreAudioUtilityClasses/AUScopeElement.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAAUParameter.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAAudioChannelLayout.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAMutex.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAStreamBasicDescription.cpp"\r
-#include "AU/CoreAudioUtilityClasses/CAVectorUnit.cpp"\r
-#include "AU/CoreAudioUtilityClasses/ComponentBase.cpp"\r
-#include "AU/CoreAudioUtilityClasses/MusicDeviceBase.cpp"\r
+#if ! defined (MAC_OS_VERSION_11_0) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_VERSION_11_0\r
+// These constants are only defined in the macOS 11+ SDKs\r
+\r
+enum MIDICVStatus : unsigned int\r
+{\r
+    kMIDICVStatusNoteOff                = 0x8,\r
+    kMIDICVStatusNoteOn                 = 0x9,\r
+    kMIDICVStatusPolyPressure           = 0xA,\r
+    kMIDICVStatusControlChange          = 0xB,\r
+    kMIDICVStatusProgramChange          = 0xC,\r
+    kMIDICVStatusChannelPressure        = 0xD,\r
+    kMIDICVStatusPitchBend              = 0xE,\r
+    kMIDICVStatusRegisteredPNC          = 0x0,\r
+    kMIDICVStatusAssignablePNC          = 0x1,\r
+    kMIDICVStatusRegisteredControl      = 0x2,\r
+    kMIDICVStatusAssignableControl      = 0x3,\r
+    kMIDICVStatusRelRegisteredControl   = 0x4,\r
+    kMIDICVStatusRelAssignableControl   = 0x5,\r
+    kMIDICVStatusPerNotePitchBend       = 0x6,\r
+    kMIDICVStatusPerNoteMgmt            = 0xF\r
+};\r
+\r
+#endif\r
+\r
+#include "AU/AudioUnitSDK/AUBase.cpp"\r
+#include "AU/AudioUnitSDK/AUBuffer.cpp"\r
+#include "AU/AudioUnitSDK/AUBufferAllocator.cpp"\r
+#include "AU/AudioUnitSDK/AUEffectBase.cpp"\r
+#include "AU/AudioUnitSDK/AUInputElement.cpp"\r
+#include "AU/AudioUnitSDK/AUMIDIBase.cpp"\r
+#include "AU/AudioUnitSDK/AUMIDIEffectBase.cpp"\r
+#include "AU/AudioUnitSDK/AUOutputElement.cpp"\r
+#include "AU/AudioUnitSDK/AUPlugInDispatch.cpp"\r
+#include "AU/AudioUnitSDK/AUScopeElement.cpp"\r
+#include "AU/AudioUnitSDK/ComponentBase.cpp"\r
+#include "AU/AudioUnitSDK/MusicDeviceBase.cpp"\r
 \r
 #undef verify\r
 #undef verify_noerr\r
index 0eaf46850173c5440faf40378b2e41a886397cb2..e4c5c25bb0181bfd9dad5ed33fdfd4a0fa7e6e3c 100644 (file)
@@ -44,6 +44,8 @@
  JUCE_CREATE_APPLICATION_DEFINE(juce::StandaloneFilterApp)\r
 #endif\r
 \r
-JUCE_MAIN_FUNCTION_DEFINITION\r
+#if ! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_ENTRYPOINT\r
+ JUCE_MAIN_FUNCTION_DEFINITION\r
+#endif\r
 \r
 #endif\r
index a5b7a1f5fe8ce101be3b63e971091449892c9b04..50dfd51fa5c2acc4b84cfcb167434623a1357cc1 100644 (file)
 namespace juce\r
 {\r
 \r
-inline AudioProcessor* JUCE_API JUCE_CALLTYPE createPluginFilterOfType (AudioProcessor::WrapperType type)\r
+inline std::unique_ptr<AudioProcessor> createPluginFilterOfType (AudioProcessor::WrapperType type)\r
 {\r
+    PluginHostType::jucePlugInClientCurrentWrapperType = type;\r
     AudioProcessor::setTypeOfNextNewPlugin (type);\r
-    AudioProcessor* const pluginInstance = ::createPluginFilter();\r
+    auto pluginInstance = rawToUniquePtr (::createPluginFilter());\r
     AudioProcessor::setTypeOfNextNewPlugin (AudioProcessor::wrapperType_Undefined);\r
 \r
     // your createPluginFilter() method must return an object!\r
     jassert (pluginInstance != nullptr && pluginInstance->wrapperType == type);\r
 \r
    #if JucePlugin_Enable_ARA\r
-    jassert (dynamic_cast<juce::AudioProcessorARAExtension*> (pluginInstance) != nullptr);\r
+    jassert (dynamic_cast<juce::AudioProcessorARAExtension*> (pluginInstance.get()) != nullptr);\r
    #endif\r
 \r
     return pluginInstance;\r
index 646d07285b333f2ed9837af9cc495554dd87e614..267a86fe1134c7346caa78792755302c71afc165 100644 (file)
@@ -25,8 +25,6 @@
 \r
 #if JUCE_LINUX || JUCE_BSD\r
 \r
-#include <thread>\r
-\r
 namespace juce\r
 {\r
 \r
@@ -34,15 +32,15 @@ namespace juce
 bool dispatchNextMessageOnSystemQueue (bool returnIfNoPendingMessages);\r
 \r
 /** @internal */\r
-class MessageThread\r
+class MessageThread : public Thread\r
 {\r
 public:\r
-    MessageThread()\r
+    MessageThread() : Thread ("JUCE Plugin Message Thread")\r
     {\r
         start();\r
     }\r
 \r
-    ~MessageThread()\r
+    ~MessageThread() override\r
     {\r
         MessageManager::getInstance()->stopDispatchLoop();\r
         stop();\r
@@ -50,51 +48,37 @@ public:
 \r
     void start()\r
     {\r
-        if (isRunning())\r
-            stop();\r
-\r
-        shouldExit = false;\r
-\r
-        thread = std::thread { [this]\r
-        {\r
-            Thread::setCurrentThreadPriority (7);\r
-            Thread::setCurrentThreadName ("JUCE Plugin Message Thread");\r
-\r
-            MessageManager::getInstance()->setCurrentThreadAsMessageThread();\r
-            XWindowSystem::getInstance();\r
+        startThread (Priority::high);\r
 \r
-            threadInitialised.signal();\r
-\r
-            for (;;)\r
-            {\r
-                if (! dispatchNextMessageOnSystemQueue (true))\r
-                    Thread::sleep (1);\r
-\r
-                if (shouldExit)\r
-                    break;\r
-            }\r
-        } };\r
-\r
-        threadInitialised.wait();\r
+        // Wait for setCurrentThreadAsMessageThread() and getInstance to be executed\r
+        // before leaving this method\r
+        threadInitialised.wait (10000);\r
     }\r
 \r
     void stop()\r
     {\r
-        if (! isRunning())\r
-            return;\r
-\r
-        shouldExit = true;\r
-        thread.join();\r
+        signalThreadShouldExit();\r
+        stopThread (-1);\r
     }\r
 \r
-    bool isRunning() const noexcept  { return thread.joinable(); }\r
+    bool isRunning() const noexcept  { return isThreadRunning(); }\r
 \r
-private:\r
-    WaitableEvent threadInitialised;\r
-    std::thread thread;\r
+    void run() override\r
+    {\r
+        MessageManager::getInstance()->setCurrentThreadAsMessageThread();\r
+        XWindowSystem::getInstance();\r
 \r
-    std::atomic<bool> shouldExit { false };\r
+        threadInitialised.signal();\r
 \r
+        while (! threadShouldExit())\r
+        {\r
+            if (! dispatchNextMessageOnSystemQueue (true))\r
+                Thread::sleep (1);\r
+        }\r
+    }\r
+\r
+private:\r
+    WaitableEvent threadInitialised;\r
     JUCE_DECLARE_NON_MOVEABLE (MessageThread)\r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (MessageThread)\r
 };\r
index 0c2e7a179247d2d083575447ef5726902e652602..f6b4b2689deb63f1bf3ab7df5b16122c6b4dcf23 100644 (file)
@@ -56,7 +56,7 @@ namespace juce
       const auto juce_strcat  = [] (auto&& head, auto&&... tail) { strcat_s  (head, numElementsInArray (head), tail...); };\r
       const auto juce_sscanf  = [] (auto&&... args)              { sscanf_s  (args...); };\r
      #else\r
-      const auto juce_sprintf = [] (auto&&... args)              { sprintf   (args...); };\r
+      const auto juce_sprintf = [] (auto&& head, auto&&... tail) { snprintf  (head, (size_t) numElementsInArray (head), tail...); };\r
       const auto juce_strcpy  = [] (auto&&... args)              { strcpy    (args...); };\r
       const auto juce_strcat  = [] (auto&&... args)              { strcat    (args...); };\r
       const auto juce_sscanf  = [] (auto&&... args)              { sscanf    (args...); };\r
@@ -134,7 +134,10 @@ namespace juce
 \r
 #if JucePlugin_Build_VST\r
  bool JUCE_API handleManufacturerSpecificVST2Opcode (int32 index, pointer_sized_int value, void* ptr, float);\r
- bool JUCE_API handleManufacturerSpecificVST2Opcode (int32 index, pointer_sized_int value, void* ptr, float)\r
+ bool JUCE_API handleManufacturerSpecificVST2Opcode ([[maybe_unused]] int32 index,\r
+                                                     [[maybe_unused]] pointer_sized_int value,\r
+                                                     [[maybe_unused]] void* ptr,\r
+                                                     float)\r
  {\r
     #if VST3_REPLACEMENT_AVAILABLE\r
      if ((index == (int32) ByteOrder::bigEndianInt ("stCA") || index == (int32) ByteOrder::bigEndianInt ("stCa"))\r
@@ -145,8 +148,6 @@ namespace juce
          ::memcpy (ptr, fuid, 16);\r
          return true;\r
      }\r
-    #else\r
-     ignoreUnused (index, value, ptr);\r
     #endif\r
      return false;\r
  }\r
index 9ba57bea469753b805be1707f5fe5543ef5e796c..3e5c029bf47c0bd59078966ced48762b5cd77935 100644 (file)
@@ -64,10 +64,8 @@ void AudioPluginFormatManager::addDefaultFormats()
 \r
    #if JUCE_DEBUG\r
     // you should only call this method once!\r
-    for (auto* format : formats)\r
+    for (auto* format [[maybe_unused]] : formats)\r
     {\r
-        ignoreUnused (format);\r
-\r
        #if HAS_VST\r
         jassert (dynamic_cast<VSTPluginFormat*> (format) == nullptr);\r
        #endif\r
index 8f2260d063c46478ab1fd0e7fa6496c17d5ec140..07ce919af179d94dab8b9518ff94c5c59b8dc573 100644 (file)
@@ -67,7 +67,7 @@
   #define LILV_DEFAULT_LV2_PATH \\r
     "%APPDATA%\\LV2"                LILV_PATH_SEP \\r
     "%COMMONPROGRAMFILES%\\LV2"\r
- #elif JUCE_LINUX || JUCE_ANDROID\r
+ #elif JUCE_LINUX || JUCE_BSD || JUCE_ANDROID\r
   #define LILV_DEFAULT_LV2_PATH \\r
     "~/.lv2"                        LILV_PATH_SEP \\r
     "/usr/lib/lv2"                  LILV_PATH_SEP \\r
index e5d40290fc4a138ea251adcd4bbb9bae278016bf..ef7b30ad05ffcd2b6b8887825474b26cbc7eb750 100644 (file)
@@ -179,14 +179,15 @@ namespace AudioUnitFormatHelpers
         return false;\r
     }\r
 \r
-    static bool getComponentDescFromFile (const String& fileOrIdentifier, AudioComponentDescription& desc,\r
-                                          String& name, String& version, String& manufacturer)\r
+    static bool getComponentDescFromFile ([[maybe_unused]] const String& fileOrIdentifier,\r
+                                          [[maybe_unused]] AudioComponentDescription& desc,\r
+                                          [[maybe_unused]] String& name,\r
+                                          [[maybe_unused]] String& version,\r
+                                          [[maybe_unused]] String& manufacturer)\r
     {\r
         zerostruct (desc);\r
 \r
        #if JUCE_IOS\r
-        ignoreUnused (fileOrIdentifier, name, version, manufacturer);\r
-\r
         return false;\r
        #else\r
         const File file (fileOrIdentifier);\r
@@ -434,7 +435,7 @@ namespace AudioUnitFormatHelpers
     }\r
 }\r
 \r
-static bool hasARAExtension (AudioUnit audioUnit)\r
+static bool hasARAExtension ([[maybe_unused]] AudioUnit audioUnit)\r
 {\r
    #if JUCE_PLUGINHOST_ARA\r
     UInt32 propertySize = sizeof (ARA::ARAAudioUnitFactory);\r
@@ -449,8 +450,6 @@ static bool hasARAExtension (AudioUnit audioUnit)
 \r
     if ((status == noErr) && (propertySize == sizeof (ARA::ARAAudioUnitFactory)) && ! isWriteable)\r
         return true;\r
-   #else\r
-    ignoreUnused (audioUnit);\r
    #endif\r
 \r
     return false;\r
@@ -465,7 +464,7 @@ using AudioUnitUniquePtr = std::unique_ptr<std::remove_pointer_t<AudioUnit>, Aud
 using AudioUnitSharedPtr = std::shared_ptr<std::remove_pointer_t<AudioUnit>>;\r
 using AudioUnitWeakPtr = std::weak_ptr<std::remove_pointer_t<AudioUnit>>;\r
 \r
-static std::shared_ptr<const ARA::ARAFactory> getARAFactory (AudioUnitSharedPtr audioUnit)\r
+static std::shared_ptr<const ARA::ARAFactory> getARAFactory ([[maybe_unused]] AudioUnitSharedPtr audioUnit)\r
 {\r
    #if JUCE_PLUGINHOST_ARA\r
     jassert (audioUnit != nullptr);\r
@@ -491,8 +490,6 @@ static std::shared_ptr<const ARA::ARAFactory> getARAFactory (AudioUnitSharedPtr
                                           [owningAuPtr = std::move (audioUnit)]() {});\r
         }\r
     }\r
-   #else\r
-    ignoreUnused (audioUnit);\r
    #endif\r
 \r
     return {};\r
@@ -1137,24 +1134,20 @@ public:
             return false;\r
 \r
         // did anything actually change\r
-        if (layoutHasChanged)\r
-        {\r
-            bool success = (AudioUnitInitialize (audioUnit) == noErr);\r
-\r
-            // Some plug-ins require the LayoutTag to be set after initialization\r
-            if (success)\r
-                success = syncBusLayouts (layouts, true, layoutHasChanged);\r
+        if (! layoutHasChanged)\r
+            return true;\r
 \r
-            AudioUnitUninitialize (audioUnit);\r
+        // Some plug-ins require the LayoutTag to be set after initialization\r
+        const auto success = (AudioUnitInitialize (audioUnit) == noErr)\r
+                             && syncBusLayouts (layouts, true, layoutHasChanged);\r
 \r
-            if (! success)\r
-                // make sure that the layout is back to it's original state\r
-                syncBusLayouts (getBusesLayout(), false, layoutHasChanged);\r
+        AudioUnitUninitialize (audioUnit);\r
 \r
-            return success;\r
-        }\r
+        if (! success)\r
+            // make sure that the layout is back to its original state\r
+            syncBusLayouts (getBusesLayout(), false, layoutHasChanged);\r
 \r
-        return true;\r
+        return success;\r
     }\r
 \r
     //==============================================================================\r
@@ -2297,43 +2290,43 @@ private:
         if (p != nullptr) *p = value;\r
     }\r
 \r
-    OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const\r
+    /*  If the AudioPlayHead is available, and has valid PositionInfo, this will return the result\r
+        of calling the specified getter on that PositionInfo. Otherwise, this will return a\r
+        default-constructed instance of the same type.\r
+\r
+        For getters that return an Optional, this function will return a nullopt if the playhead or\r
+        position info is invalid.\r
+\r
+        For getters that return a bool, this function will return false if the playhead or position\r
+        info is invalid.\r
+    */\r
+    template <typename Result>\r
+    Result getFromPlayHead (Result (AudioPlayHead::PositionInfo::* member)() const) const\r
     {\r
         if (auto* ph = getPlayHead())\r
-        {\r
             if (const auto pos = ph->getPosition())\r
-            {\r
-                setIfNotNull (outCurrentBeat, pos->getPpqPosition().orFallback (0.0));\r
-                setIfNotNull (outCurrentTempo, pos->getBpm().orFallback (0.0));\r
-                return noErr;\r
-            }\r
-        }\r
+                return ((*pos).*member)();\r
+\r
+        return {};\r
+    }\r
 \r
-        setIfNotNull (outCurrentBeat, 0);\r
-        setIfNotNull (outCurrentTempo, 120.0);\r
+    OSStatus getBeatAndTempo (Float64* outCurrentBeat, Float64* outCurrentTempo) const\r
+    {\r
+        setIfNotNull (outCurrentBeat,  getFromPlayHead (&AudioPlayHead::PositionInfo::getPpqPosition).orFallback (0));\r
+        setIfNotNull (outCurrentTempo, getFromPlayHead (&AudioPlayHead::PositionInfo::getBpm).orFallback (120.0));\r
         return noErr;\r
     }\r
 \r
     OSStatus getMusicalTimeLocation (UInt32* outDeltaSampleOffsetToNextBeat, Float32* outTimeSig_Numerator,\r
                                      UInt32* outTimeSig_Denominator, Float64* outCurrentMeasureDownBeat) const\r
     {\r
-        if (auto* ph = getPlayHead())\r
-        {\r
-            if (const auto pos = ph->getPosition())\r
-            {\r
-                const auto signature = pos->getTimeSignature().orFallback (AudioPlayHead::TimeSignature{});\r
-                setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0); //xxx\r
-                setIfNotNull (outTimeSig_Numerator,   (UInt32) signature.numerator);\r
-                setIfNotNull (outTimeSig_Denominator, (UInt32) signature.denominator);\r
-                setIfNotNull (outCurrentMeasureDownBeat, pos->getPpqPositionOfLastBarStart().orFallback (0.0)); //xxx wrong\r
-                return noErr;\r
-            }\r
-        }\r
+        setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0); //xxx\r
+        setIfNotNull (outCurrentMeasureDownBeat, getFromPlayHead (&AudioPlayHead::PositionInfo::getPpqPositionOfLastBarStart).orFallback (0.0));\r
+\r
+        const auto signature = getFromPlayHead (&AudioPlayHead::PositionInfo::getTimeSignature).orFallback (AudioPlayHead::TimeSignature{});\r
+        setIfNotNull (outTimeSig_Numerator,   (UInt32) signature.numerator);\r
+        setIfNotNull (outTimeSig_Denominator, (UInt32) signature.denominator);\r
 \r
-        setIfNotNull (outDeltaSampleOffsetToNextBeat, (UInt32) 0);\r
-        setIfNotNull (outTimeSig_Numerator, (UInt32) 4);\r
-        setIfNotNull (outTimeSig_Denominator, (UInt32) 4);\r
-        setIfNotNull (outCurrentMeasureDownBeat, 0);\r
         return noErr;\r
     }\r
 \r
@@ -2341,34 +2334,16 @@ private:
                                 Float64* outCurrentSampleInTimeLine, Boolean* outIsCycling,\r
                                 Float64* outCycleStartBeat, Float64* outCycleEndBeat)\r
     {\r
-        if (auto* ph = getPlayHead())\r
-        {\r
-            AudioPlayHead::CurrentPositionInfo result;\r
-\r
-            if (ph->getCurrentPosition (result))\r
-            {\r
-                setIfNotNull (outIsPlaying, result.isPlaying);\r
+        const auto nowPlaying = getFromPlayHead (&AudioPlayHead::PositionInfo::getIsPlaying);\r
+        setIfNotNull (outIsPlaying, nowPlaying);\r
+        setIfNotNull (outTransportStateChanged, std::exchange (wasPlaying, nowPlaying) != nowPlaying);\r
+        setIfNotNull (outCurrentSampleInTimeLine, getFromPlayHead (&AudioPlayHead::PositionInfo::getTimeInSamples).orFallback (0));\r
+        setIfNotNull (outIsCycling, getFromPlayHead (&AudioPlayHead::PositionInfo::getIsLooping));\r
 \r
-                if (outTransportStateChanged != nullptr)\r
-                {\r
-                    *outTransportStateChanged = result.isPlaying != wasPlaying;\r
-                    wasPlaying = result.isPlaying;\r
-                }\r
+        const auto loopPoints = getFromPlayHead (&AudioPlayHead::PositionInfo::getLoopPoints).orFallback (AudioPlayHead::LoopPoints{});\r
+        setIfNotNull (outCycleStartBeat, loopPoints.ppqStart);\r
+        setIfNotNull (outCycleEndBeat, loopPoints.ppqEnd);\r
 \r
-                setIfNotNull (outCurrentSampleInTimeLine, result.timeInSamples);\r
-                setIfNotNull (outIsCycling, result.isLooping);\r
-                setIfNotNull (outCycleStartBeat, result.ppqLoopStart);\r
-                setIfNotNull (outCycleEndBeat, result.ppqLoopEnd);\r
-                return noErr;\r
-            }\r
-        }\r
-\r
-        setIfNotNull (outIsPlaying, false);\r
-        setIfNotNull (outTransportStateChanged, false);\r
-        setIfNotNull (outCurrentSampleInTimeLine, 0);\r
-        setIfNotNull (outIsCycling, false);\r
-        setIfNotNull (outCycleStartBeat, 0.0);\r
-        setIfNotNull (outCycleEndBeat, 0.0);\r
         return noErr;\r
     }\r
 \r
@@ -2662,13 +2637,12 @@ public:
         }\r
     }\r
 \r
-    void embedViewController (JUCE_IOS_MAC_VIEW* pluginView, const CGSize& size)\r
+    void embedViewController (JUCE_IOS_MAC_VIEW* pluginView, [[maybe_unused]] const CGSize& size)\r
     {\r
         wrapper.setView (pluginView);\r
         waitingForViewCallback = false;\r
 \r
       #if JUCE_MAC\r
-        ignoreUnused (size);\r
         if (pluginView != nil)\r
             wrapper.resizeToFitView();\r
       #else\r
@@ -2704,7 +2678,7 @@ private:
 \r
     bool waitingForViewCallback = false;\r
 \r
-    bool createView (bool createGenericViewIfNeeded)\r
+    bool createView ([[maybe_unused]] bool createGenericViewIfNeeded)\r
     {\r
         JUCE_IOS_MAC_VIEW* pluginView = nil;\r
         UInt32 dataSize = 0;\r
@@ -2778,8 +2752,6 @@ private:
 \r
             pluginView = [[AUGenericView alloc] initWithAudioUnit: plugin.audioUnit];\r
         }\r
-       #else\r
-        ignoreUnused (createGenericViewIfNeeded);\r
        #endif\r
 \r
         wrapper.setView (pluginView);\r
index cec1528a450b59395f4f11a2b3dc358c2156113d..6121dd84e8289327b21e91a1e86b231ed4782152 100644 (file)
@@ -384,10 +384,8 @@ public:
     void getCurrentProgramStateInformation (MemoryBlock& destData) override               { getStateInformation (destData); }\r
     void setCurrentProgramStateInformation (const void* data, int sizeInBytes) override   { setStateInformation (data, sizeInBytes); }\r
 \r
-    void setStateInformation (const void* data, int sizeInBytes) override\r
+    void setStateInformation (const void* data, [[maybe_unused]] int sizeInBytes) override\r
     {\r
-        ignoreUnused (sizeInBytes);\r
-\r
         auto* p = static_cast<const float*> (data);\r
 \r
         for (int i = 0; i < getParameters().size(); ++i)\r
index d3f3275dbc816713a6d04b2698a9d1a7b51fed8e..92a5a987a4737b4ea643920f6c0eeb2d4c728320 100644 (file)
@@ -615,6 +615,55 @@ static inline std::vector<ParsedGroup> findStableBusOrder (const String& mainGro
     return result;\r
 }\r
 \r
+/*  See https://www.w3.org/TeamSubmission/turtle/#sec-grammar-grammar\r
+*/\r
+static inline bool isNameStartChar (juce_wchar input)\r
+{\r
+    return ('A' <= input && input <= 'Z')\r
+        || input == '_'\r
+        || ('a' <= input && input <= 'z')\r
+        || (0x000c0 <= input && input <= 0x000d6)\r
+        || (0x000d8 <= input && input <= 0x000f6)\r
+        || (0x000f8 <= input && input <= 0x000ff)\r
+        || (0x00370 <= input && input <= 0x0037d)\r
+        || (0x0037f <= input && input <= 0x01fff)\r
+        || (0x0200c <= input && input <= 0x0200d)\r
+        || (0x02070 <= input && input <= 0x0218f)\r
+        || (0x02c00 <= input && input <= 0x02fef)\r
+        || (0x03001 <= input && input <= 0x0d7ff)\r
+        || (0x0f900 <= input && input <= 0x0fdcf)\r
+        || (0x0fdf0 <= input && input <= 0x0fffd)\r
+        || (0x10000 <= input && input <= 0xeffff);\r
+}\r
+\r
+static inline bool isNameChar (juce_wchar input)\r
+{\r
+    return isNameStartChar (input)\r
+        || input == '-'\r
+        || ('0' <= input && input <= '9')\r
+        || input == 0x000b7\r
+        || (0x00300 <= input && input <= 0x0036f)\r
+        || (0x0203f <= input && input <= 0x02040);\r
+}\r
+\r
+static inline String sanitiseStringAsTtlName (const String& input)\r
+{\r
+    if (input.isEmpty())\r
+        return {};\r
+\r
+    std::vector<juce_wchar> sanitised;\r
+    sanitised.reserve (static_cast<size_t> (input.length()));\r
+\r
+    sanitised.push_back (isNameStartChar (input[0]) ? input[0] : '_');\r
+\r
+    std::for_each (std::begin (input) + 1, std::end (input), [&] (juce_wchar x)\r
+    {\r
+        sanitised.push_back (isNameChar (x) ? x : '_');\r
+    });\r
+\r
+    return String (CharPointer_UTF32 { sanitised.data() }, sanitised.size());\r
+}\r
+\r
 }\r
 }\r
 \r
index 9ac149d798584cbf8be240b51be88baa98d45b95..4ef7f4b3b5f1c089117eedd905ab4ebebf5edbe1 100644 (file)
@@ -944,9 +944,10 @@ struct WorkSubmitter
     CriticalSection* workMutex;\r
 };\r
 \r
-template <typename Trivial, std::enable_if_t<std::is_trivial<Trivial>::value, int> = 0>\r
+template <typename Trivial>\r
 static auto toChars (Trivial value)\r
 {\r
+    static_assert (std::is_trivial_v<Trivial>);\r
     std::array<char, sizeof (Trivial)> result;\r
     writeUnaligned (result.data(), value);\r
     return result;\r
@@ -956,7 +957,7 @@ template <typename Context>
 class WorkQueue\r
 {\r
 public:\r
-    static_assert (std::is_trivial<Context>::value, "Context must be copyable as bytes");\r
+    static_assert (std::is_trivial_v<Context>, "Context must be copyable as bytes");\r
 \r
     explicit WorkQueue (int size)\r
         : fifo (size), data (static_cast<size_t> (size)) {}\r
@@ -1277,10 +1278,8 @@ private:
                                                   LV2_Options_Option* options,\r
                                                   LV2_Worker_Schedule* schedule,\r
                                                   LV2_Resize_Port_Resize* resize,\r
-                                                  LV2_Log_Log* log)\r
+                                                  [[maybe_unused]] LV2_Log_Log* log)\r
     {\r
-        ignoreUnused (log);\r
-\r
         return { LV2_Feature { LV2_STATE__loadDefaultState,         nullptr },\r
                  LV2_Feature { LV2_BUF_SIZE__boundedBlockLength,    nullptr },\r
                  LV2_Feature { LV2_URID__map,                       map },\r
@@ -1840,7 +1839,12 @@ class World
 public:\r
     World() : world (lilv_world_new()) {}\r
 \r
-    void loadAll() { lilv_world_load_all (world.get()); }\r
+    void loadAllFromPaths (const NodeString& paths)\r
+    {\r
+        lilv_world_set_option (world.get(), LILV_OPTION_LV2_PATH, paths.get());\r
+        lilv_world_load_all (world.get());\r
+    }\r
+\r
     void loadBundle   (const NodeUri& uri)      { lilv_world_load_bundle   (world.get(), uri.get()); }\r
     void unloadBundle (const NodeUri& uri)      { lilv_world_unload_bundle (world.get(), uri.get()); }\r
 \r
@@ -2507,7 +2511,7 @@ public:
             // In this case, we find the closest label by searching the midpoints of the scale\r
             // point values.\r
             const auto index = std::distance (midPoints.begin(),\r
-                                              std::lower_bound (midPoints.begin(), midPoints.end(), normalisedValue));\r
+                                              std::lower_bound (midPoints.begin(), midPoints.end(), denormalised));\r
             jassert (isPositiveAndBelow (index, info.scalePoints.size()));\r
             return info.scalePoints[(size_t) index].label;\r
         }\r
@@ -2549,6 +2553,7 @@ private:
             return {};\r
 \r
         std::vector<float> result;\r
+        result.reserve (set.size() - 1);\r
 \r
         for (auto it = std::next (set.begin()); it != set.end(); ++it)\r
             result.push_back ((std::prev (it)->value + it->value) * 0.5f);\r
@@ -2866,11 +2871,10 @@ private:
 \r
         ports.forEachPort ([&] (const PortHeader& header)\r
         {\r
-            const auto emplaced = result.emplace (header.symbol, header.index);\r
+            [[maybe_unused]] const auto emplaced = result.emplace (header.symbol, header.index);\r
 \r
             // This will complain if there are duplicate port symbols.\r
             jassert (emplaced.second);\r
-            ignoreUnused (emplaced);\r
         });\r
 \r
         return result;\r
@@ -3656,8 +3660,8 @@ private:
 \r
     union Data\r
     {\r
-        static_assert (std::is_trivial<PortBacking>::value,  "PortBacking must be trivial");\r
-        static_assert (std::is_trivial<PatchBacking>::value, "PatchBacking must be trivial");\r
+        static_assert (std::is_trivial_v<PortBacking>,  "PortBacking must be trivial");\r
+        static_assert (std::is_trivial_v<PatchBacking>, "PatchBacking must be trivial");\r
 \r
         explicit Data (PortBacking p)  : port  (p) {}\r
         explicit Data (PatchBacking p) : patch (p) {}\r
@@ -4877,10 +4881,8 @@ private:
                                                              : freeWheelingPort->info.min;\r
     }\r
 \r
-    void pushMessage (MessageHeader header, uint32_t size, const void* data)\r
+    void pushMessage (MessageHeader header, [[maybe_unused]] uint32_t size, const void* data)\r
     {\r
-        ignoreUnused (size);\r
-\r
         if (header.protocol == 0 || header.protocol == instance->urids.mLV2_UI__floatProtocol)\r
         {\r
             const auto value = readUnaligned<float> (data);\r
@@ -5187,7 +5189,7 @@ class LV2PluginFormat::Pimpl
 public:\r
     Pimpl()\r
     {\r
-        world->loadAll();\r
+        loadAllPluginsFromPaths (getDefaultLocationsToSearch());\r
 \r
         const auto tempFile = lv2ResourceFolder.getFile();\r
 \r
@@ -5250,9 +5252,9 @@ public:
         return findPluginByUri (description.fileOrIdentifier) != nullptr;\r
     }\r
 \r
-    StringArray searchPathsForPlugins (const FileSearchPath&, bool, bool)\r
+    StringArray searchPathsForPlugins (const FileSearchPath& paths, bool, bool)\r
     {\r
-        world->loadAll();\r
+        loadAllPluginsFromPaths (paths);\r
 \r
         StringArray result;\r
 \r
@@ -5262,7 +5264,30 @@ public:
         return result;\r
     }\r
 \r
-    FileSearchPath getDefaultLocationsToSearch() { return {}; }\r
+    FileSearchPath getDefaultLocationsToSearch()\r
+    {\r
+      #if JUCE_MAC\r
+        return { "~/Library/Audio/Plug-Ins/LV2;"\r
+                 "~/.lv2;"\r
+                 "/usr/local/lib/lv2;"\r
+                 "/usr/lib/lv2;"\r
+                 "/Library/Audio/Plug-Ins/LV2;" };\r
+      #elif JUCE_WINDOWS\r
+        return { "%APPDATA%\\LV2;"\r
+                 "%COMMONPROGRAMFILES%\\LV2" };\r
+      #else\r
+       #if JUCE_64BIT\r
+        if (File ("/usr/lib64/lv2").exists() || File ("/usr/local/lib64/lv2").exists())\r
+            return { "~/.lv2;"\r
+                     "/usr/lib64/lv2;"\r
+                     "/usr/local/lib64/lv2" };\r
+       #endif\r
+\r
+        return { "~/.lv2;"\r
+                 "/usr/lib/lv2;"\r
+                 "/usr/local/lib/lv2" };\r
+      #endif\r
+    }\r
 \r
     const LilvUI* findEmbeddableUi (const lv2_host::Uis* pluginUis, std::true_type)\r
     {\r
@@ -5455,6 +5480,12 @@ public:
     }\r
 \r
 private:\r
+    void loadAllPluginsFromPaths (const FileSearchPath& path)\r
+    {\r
+        const auto joined = path.toStringWithSeparator (LILV_PATH_SEP);\r
+        world->loadAllFromPaths (world->newString (joined.toRawUTF8()));\r
+    }\r
+\r
     struct Free { void operator() (char* ptr) const noexcept { free (ptr); } };\r
     using StringPtr = std::unique_ptr<char, Free>;\r
 \r
index a4c269af164e4dcc32d8088e42b43ae111c9f0a1..bc81cdb6f4d5dc55188e19df86b9ea29b959019a 100644 (file)
@@ -50,6 +50,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4100 4200 4244 4267 4389 4702 4706 4800 4996 63
 extern "C"\r
 {\r
 \r
+#include <math.h>\r
+\r
 #define is_windows_path serd_is_windows_path\r
 \r
 #include "serd/src/base64.c"\r
@@ -57,6 +59,20 @@ extern "C"
 #include "serd/src/env.c"\r
 #include "serd/src/n3.c"\r
 #undef TRY\r
+\r
+// node.c will replace isnan and isinf with _isnan and _finite if the former symbols are undefined.\r
+// MinGW declares these as normal functions rather than as preprocessor definitions, causing the build to fail.\r
+#if defined (_WIN32) && defined (__GNUC__)\r
+\r
+namespace Utils\r
+{\r
+    inline int _isnan  (double x) noexcept { return isnan (x); }\r
+    inline int _finite (double x) noexcept { return ! isinf (x); }\r
+} // namespace Utils\r
+\r
+using namespace Utils;\r
+#endif\r
+\r
 #include "serd/src/node.c"\r
 #include "serd/src/reader.c"\r
 #include "serd/src/string.c"\r
index 77544c7ae3741637dd5a90742fbd60f9c956ed71..cf7f2a81437c2c5a24e438105d500fc75e72732a 100644 (file)
@@ -627,7 +627,7 @@ static bool validateLayouts (Iterator first, Iterator last, const std::vector<Dy
         const auto anyChannelIsNull = std::any_of (busPtr, busPtr + it->numChannels, [] (auto* ptr) { return ptr == nullptr; });\r
 \r
         // Null channels are allowed if the bus is inactive\r
-        if ((mapIterator->isHostActive() && anyChannelIsNull) || ((int) mapIterator->size() != it->numChannels))\r
+        if (mapIterator->isHostActive() && (anyChannelIsNull || (int) mapIterator->size() != it->numChannels))\r
             return false;\r
     }\r
 \r
@@ -1261,7 +1261,7 @@ private:
 \r
         const auto controlEvent = toVst3ControlEvent (msg);\r
 \r
-        if (! controlEvent.hasValue())\r
+        if (! controlEvent.has_value())\r
             return false;\r
 \r
         const auto controlParamID = midiMapping->getMapping (createSafeChannel (msg.getChannel()),\r
@@ -1561,7 +1561,7 @@ private:
         Steinberg::Vst::ParamValue paramValue;\r
     };\r
 \r
-    static Optional<Vst3MidiControlEvent> toVst3ControlEvent (const MidiMessage& msg)\r
+    static std::optional<Vst3MidiControlEvent> toVst3ControlEvent (const MidiMessage& msg)\r
     {\r
         if (msg.isController())\r
             return Vst3MidiControlEvent { (Steinberg::Vst::CtrlNumber) msg.getControllerNumber(), msg.getControllerValue() / 127.0 };\r
index 297776b3cc295bb70d4ca18a89390872d5acf55d..cd757c39621814702ad8243a75c1d71ef79710a5 100644 (file)
@@ -34,6 +34,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_LEVEL_MSVC (0, 4505 4702 6011 6031 6221 6386 6387 633
 \r
 JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-copy-dtor",\r
                                      "-Wnon-virtual-dtor",\r
+                                     "-Wdeprecated",\r
                                      "-Wreorder",\r
                                      "-Wunsequenced",\r
                                      "-Wint-to-pointer-cast",\r
@@ -67,7 +68,8 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-copy-dtor",
                                      "-Wtype-limits",\r
                                      "-Wcpp",\r
                                      "-W#warnings",\r
-                                     "-Wmaybe-uninitialized")\r
+                                     "-Wmaybe-uninitialized",\r
+                                     "-Wunused-but-set-variable")\r
 \r
 #undef DEVELOPMENT\r
 #define DEVELOPMENT 0  // This avoids a Clang warning in Steinberg code about unused values\r
index cfa7b3cf26fc1a513503f5f3127e598a5f529c00..7865d50bdad1fed9c083fff7690f33c11c45404f 100644 (file)
@@ -375,9 +375,8 @@ struct VST3HostContext  : public Vst::IComponentHandler,  // From VST V3.0.0
     tresult PLUGIN_API setDirty (TBool) override;\r
 \r
     //==============================================================================\r
-    tresult PLUGIN_API requestOpenEditor (FIDString name) override\r
+    tresult PLUGIN_API requestOpenEditor ([[maybe_unused]] FIDString name) override\r
     {\r
-        ignoreUnused (name);\r
         jassertfalse;\r
         return kResultFalse;\r
     }\r
@@ -762,9 +761,9 @@ private:
             const auto iter = attributes.find (attr);\r
 \r
             if (iter != attributes.end())\r
-                iter->second = Attribute (std::move (value));\r
+                iter->second = Attribute (std::forward<Value> (value));\r
             else\r
-                attributes.emplace (attr, Attribute (std::move (value)));\r
+                attributes.emplace (attr, Attribute (std::forward<Value> (value)));\r
 \r
             return kResultTrue;\r
         }\r
@@ -1388,7 +1387,7 @@ static int compareWithString (Type (&charArray)[N], const String& str)
 }\r
 \r
 template <typename Callback>\r
-static void forEachARAFactory (IPluginFactory* pluginFactory, Callback&& cb)\r
+static void forEachARAFactory ([[maybe_unused]] IPluginFactory* pluginFactory, [[maybe_unused]] Callback&& cb)\r
 {\r
    #if JUCE_PLUGINHOST_ARA && (JUCE_MAC || JUCE_WINDOWS || JUCE_LINUX)\r
     const auto numClasses = pluginFactory->countClasses();\r
@@ -1404,12 +1403,11 @@ static void forEachARAFactory (IPluginFactory* pluginFactory, Callback&& cb)
                 break;\r
         }\r
     }\r
-   #else\r
-    ignoreUnused (pluginFactory, cb);\r
    #endif\r
 }\r
 \r
-static std::shared_ptr<const ARA::ARAFactory> getARAFactory (Steinberg::IPluginFactory* pluginFactory, const String& pluginName)\r
+static std::shared_ptr<const ARA::ARAFactory> getARAFactory ([[maybe_unused]] Steinberg::IPluginFactory* pluginFactory,\r
+                                                             [[maybe_unused]] const String& pluginName)\r
 {\r
     std::shared_ptr<const ARA::ARAFactory> factory;\r
 \r
@@ -1432,8 +1430,6 @@ static std::shared_ptr<const ARA::ARAFactory> getARAFactory (Steinberg::IPluginF
 \r
                            return true;\r
                        });\r
-   #else\r
-    ignoreUnused (pluginFactory, pluginName);\r
    #endif\r
 \r
     return factory;\r
@@ -1667,8 +1663,8 @@ private:
                 return;\r
             }\r
 \r
-            const auto attachedResult = view->attached ((void*) pluginHandle, defaultVST3WindowType);\r
-            ignoreUnused (warnOnFailure (attachedResult));\r
+            [[maybe_unused]] const auto attachedResult = view->attached ((void*) pluginHandle, defaultVST3WindowType);\r
+            [[maybe_unused]] const auto warning = warnOnFailure (attachedResult);\r
 \r
             if (attachedResult == kResultOk)\r
                 attachedCalled = true;\r
@@ -1689,11 +1685,10 @@ private:
     {\r
         if (scaleInterface != nullptr)\r
         {\r
-            const auto result = scaleInterface->setContentScaleFactor ((Steinberg::IPlugViewContentScaleSupport::ScaleFactor) getEffectiveScale());\r
-            ignoreUnused (result);\r
+            [[maybe_unused]] const auto result = scaleInterface->setContentScaleFactor ((Steinberg::IPlugViewContentScaleSupport::ScaleFactor) getEffectiveScale());\r
 \r
            #if ! JUCE_MAC\r
-            ignoreUnused (warnOnFailure (result));\r
+            [[maybe_unused]] const auto warning = warnOnFailure (result);\r
            #endif\r
         }\r
     }\r
@@ -1885,8 +1880,7 @@ struct VST3ComponentHolder
         if (classIdx >= 0)\r
         {\r
             PClassInfo info;\r
-            bool success = (factory->getClassInfo (classIdx, &info) == kResultOk);\r
-            ignoreUnused (success);\r
+            [[maybe_unused]] bool success = (factory->getClassInfo (classIdx, &info) == kResultOk);\r
             jassert (success);\r
 \r
             VSTComSmartPtr<IPluginFactory2> pf2;\r
@@ -2217,6 +2211,7 @@ public:
         void setValue (float newValue) override\r
         {\r
             pluginInstance.cachedParamValues.set (vstParamIndex, newValue);\r
+            pluginInstance.parameterDispatcher.push (vstParamIndex, newValue);\r
         }\r
 \r
         /*  If we're syncing the editor to the processor, the processor won't need to\r
@@ -2392,7 +2387,7 @@ public:
 \r
         auto configureParameters = [this]\r
         {\r
-            refreshParameterList();\r
+            initialiseParameterList();\r
             synchroniseStates();\r
             syncProgramNames();\r
         };\r
@@ -2511,6 +2506,11 @@ public:
 \r
         using namespace Vst;\r
 \r
+        // If the plugin has already been activated (prepareToPlay has been called twice without\r
+        // a matching releaseResources call) deactivate it so that the speaker layout and bus\r
+        // activation can be updated safely.\r
+        deactivate();\r
+\r
         ProcessSetup setup;\r
         setup.symbolicSampleSize    = isUsingDoublePrecision() ? kSample64 : kSample32;\r
         setup.maxSamplesPerBlock    = estimatedSamplesPerBlock;\r
@@ -2565,19 +2565,7 @@ public:
     void releaseResources() override\r
     {\r
         const SpinLock::ScopedLockType lock (processMutex);\r
-\r
-        if (! isActive)\r
-            return; // Avoids redundantly calling things like setActive\r
-\r
-        isActive = false;\r
-\r
-        if (processor != nullptr)\r
-            warnOnFailureIfImplemented (processor->setProcessing (false));\r
-\r
-        if (holder->component != nullptr)\r
-            warnOnFailure (holder->component->setActive (false));\r
-\r
-        setStateForAllMidiBuses (false);\r
+        deactivate();\r
     }\r
 \r
     bool supportsDoublePrecisionProcessing() const override\r
@@ -2693,11 +2681,6 @@ public:
             inputParameterChanges->set (cachedParamValues.getParamID (index), value);\r
         });\r
 \r
-        inputParameterChanges->forEach ([&] (Steinberg::int32 index, float value)\r
-        {\r
-            parameterDispatcher.push (index, value);\r
-        });\r
-\r
         processor->process (data);\r
 \r
         outputParameterChanges->forEach ([&] (Steinberg::int32 index, float value)\r
@@ -3098,12 +3081,28 @@ public:
     }\r
 \r
     /** @note Not applicable to VST3 */\r
-    void setCurrentProgramStateInformation (const void* data, int sizeInBytes) override\r
+    void setCurrentProgramStateInformation ([[maybe_unused]] const void* data,\r
+                                            [[maybe_unused]] int sizeInBytes) override\r
     {\r
-        ignoreUnused (data, sizeInBytes);\r
     }\r
 \r
 private:\r
+    void deactivate()\r
+    {\r
+        if (! isActive)\r
+            return;\r
+\r
+        isActive = false;\r
+\r
+        if (processor != nullptr)\r
+            warnOnFailureIfImplemented (processor->setProcessing (false));\r
+\r
+        if (holder->component != nullptr)\r
+            warnOnFailure (holder->component->setActive (false));\r
+\r
+        setStateForAllMidiBuses (false);\r
+    }\r
+\r
     //==============================================================================\r
    #if JUCE_LINUX || JUCE_BSD\r
     SharedResourcePointer<RunLoop> runLoop;\r
@@ -3213,7 +3212,7 @@ private:
         }\r
     }\r
 \r
-    void refreshParameterList() override\r
+    void initialiseParameterList()\r
     {\r
         AudioProcessorParameterGroup newParameterTree;\r
 \r
index fbbc1a4f6be3f376cb755ea3ab90b75f226d9971..1f38a2a9eee530f2da83eb57f88f7017d84bb806 100644 (file)
@@ -66,9 +66,6 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4355)
  #ifndef WM_APPCOMMAND\r
   #define WM_APPCOMMAND 0x0319\r
  #endif\r
-\r
- extern "C" void _fpreset();\r
- extern "C" void _clearfp();\r
 #elif ! JUCE_WINDOWS\r
  static void _fpreset() {}\r
  static void _clearfp() {}\r
@@ -707,7 +704,7 @@ struct ModuleHandle    : public ReferenceCountedObject
                 if (auto hGlob = LoadResource (dllModule, res))\r
                 {\r
                     auto* data = static_cast<const char*> (LockResource (hGlob));\r
-                    return String::fromUTF8 (data, SizeofResource (dllModule, res));\r
+                    return String::fromUTF8 (data, (int) SizeofResource (dllModule, res));\r
                 }\r
             }\r
         }\r
@@ -829,6 +826,34 @@ static const int defaultVSTBlockSizeValue = 512;
 \r
 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)\r
 \r
+class TempChannelPointers\r
+{\r
+public:\r
+    template <typename T>\r
+    auto getArrayOfModifiableWritePointers (AudioBuffer<T>& buffer)\r
+    {\r
+        auto& pointers = getPointers (Tag<T>{});\r
+\r
+        jassert (buffer.getNumChannels() <= static_cast<int> (pointers.capacity()));\r
+        pointers.resize (jmax (pointers.size(), (size_t) buffer.getNumChannels()));\r
+\r
+        std::copy (buffer.getArrayOfWritePointers(),\r
+                   buffer.getArrayOfWritePointers() + buffer.getNumChannels(),\r
+                   pointers.begin());\r
+\r
+        return pointers.data();\r
+    }\r
+\r
+private:\r
+    template <typename> struct Tag {};\r
+\r
+    auto& getPointers (Tag<float>)  { return floatPointers; }\r
+    auto& getPointers (Tag<double>) { return doublePointers; }\r
+\r
+    std::vector<float*>  floatPointers  { 128 };\r
+    std::vector<double*> doublePointers { 128 };\r
+};\r
+\r
 //==============================================================================\r
 struct VSTPluginInstance final   : public AudioPluginInstance,\r
                                    private Timer,\r
@@ -2026,6 +2051,7 @@ private:
     bool lastProcessBlockCallWasBypass = false, vstSupportsBypass = false;\r
     mutable StringArray programNames;\r
     AudioBuffer<float> outOfPlaceBuffer;\r
+    TempChannelPointers tempChannelPointers[2];\r
 \r
     CriticalSection midiInLock;\r
     MidiBuffer incomingMidi;\r
@@ -2456,16 +2482,16 @@ private:
     {\r
         if ((vstEffect->flags & Vst2::effFlagsCanReplacing) != 0)\r
         {\r
-            vstEffect->processReplacing (vstEffect, buffer.getArrayOfWritePointers(),\r
-                                                    buffer.getArrayOfWritePointers(), sampleFrames);\r
+            vstEffect->processReplacing (vstEffect, tempChannelPointers[0].getArrayOfModifiableWritePointers (buffer),\r
+                                                    tempChannelPointers[1].getArrayOfModifiableWritePointers (buffer), sampleFrames);\r
         }\r
         else\r
         {\r
             outOfPlaceBuffer.setSize (vstEffect->numOutputs, sampleFrames);\r
             outOfPlaceBuffer.clear();\r
 \r
-            vstEffect->process (vstEffect, buffer.getArrayOfWritePointers(),\r
-                                           outOfPlaceBuffer.getArrayOfWritePointers(), sampleFrames);\r
+            vstEffect->process (vstEffect, tempChannelPointers[0].getArrayOfModifiableWritePointers (buffer),\r
+                                           tempChannelPointers[1].getArrayOfModifiableWritePointers (outOfPlaceBuffer), sampleFrames);\r
 \r
             for (int i = vstEffect->numOutputs; --i >= 0;)\r
                 buffer.copyFrom (i, 0, outOfPlaceBuffer.getReadPointer (i), sampleFrames);\r
@@ -2474,8 +2500,8 @@ private:
 \r
     inline void invokeProcessFunction (AudioBuffer<double>& buffer, int32 sampleFrames)\r
     {\r
-        vstEffect->processDoubleReplacing (vstEffect, buffer.getArrayOfWritePointers(),\r
-                                                      buffer.getArrayOfWritePointers(), sampleFrames);\r
+        vstEffect->processDoubleReplacing (vstEffect, tempChannelPointers[0].getArrayOfModifiableWritePointers (buffer),\r
+                                                      tempChannelPointers[1].getArrayOfModifiableWritePointers (buffer), sampleFrames);\r
     }\r
 \r
     //==============================================================================\r
@@ -3002,10 +3028,8 @@ public:
     }\r
 \r
     //==============================================================================\r
-    void mouseDown (const MouseEvent& e) override\r
+    void mouseDown ([[maybe_unused]] const MouseEvent& e) override\r
     {\r
-        ignoreUnused (e);\r
-\r
        #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD\r
         toFront (true);\r
        #endif\r
@@ -3110,10 +3134,10 @@ private:
         pluginWantsKeys = (dispatch (Vst2::effKeysRequired, 0, 0, nullptr, 0) == 0);\r
 \r
        #if JUCE_WINDOWS\r
-        originalWndProc = 0;\r
+        originalWndProc = nullptr;\r
         auto* pluginHWND = getPluginHWND();\r
 \r
-        if (pluginHWND == 0)\r
+        if (pluginHWND == nullptr)\r
         {\r
             isOpen = false;\r
             setSize (300, 150);\r
@@ -3153,7 +3177,7 @@ private:
                 {\r
                     ScopedThreadDPIAwarenessSetter threadDpiAwarenessSetter { pluginHWND };\r
 \r
-                    SetWindowPos (pluginHWND, 0,\r
+                    SetWindowPos (pluginHWND, nullptr,\r
                                   0, 0, rw, rh,\r
                                   SWP_NOMOVE | SWP_NOACTIVATE | SWP_NOOWNERZORDER | SWP_NOZORDER);\r
 \r
@@ -3223,11 +3247,11 @@ private:
             JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4244)\r
             auto* pluginHWND = getPluginHWND();\r
 \r
-            if (originalWndProc != 0 && pluginHWND != 0 && IsWindow (pluginHWND))\r
+            if (originalWndProc != nullptr && pluginHWND != nullptr && IsWindow (pluginHWND))\r
                 SetWindowLongPtr (pluginHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc);\r
             JUCE_END_IGNORE_WARNINGS_MSVC\r
 \r
-            originalWndProc = 0;\r
+            originalWndProc = nullptr;\r
            #elif JUCE_LINUX || JUCE_BSD\r
             pluginWindow = 0;\r
            #endif\r
@@ -3416,10 +3440,12 @@ AudioProcessorEditor* VSTPluginInstance::createEditor()
    #endif\r
 }\r
 \r
-bool VSTPluginInstance::updateSizeFromEditor (int w, int h)\r
+bool VSTPluginInstance::updateSizeFromEditor ([[maybe_unused]] int w, [[maybe_unused]] int h)\r
 {\r
+   #if ! JUCE_IOS && ! JUCE_ANDROID\r
     if (auto* editor = dynamic_cast<VSTPluginWindow*> (getActiveEditor()))\r
         return editor->updateSizeFromEditor (w, h);\r
+   #endif\r
 \r
     return false;\r
 }\r
index b0ff4b67b46d9b8e8fb99921369b7ca87095200e..8bbc3a36d1156edd374ea4b293404abe60bbc069 100644 (file)
@@ -61,7 +61,7 @@
 namespace juce\r
 {\r
 \r
-#if JUCE_PLUGINHOST_VST || (JUCE_PLUGINHOST_LADSPA && JUCE_LINUX)\r
+#if JUCE_PLUGINHOST_VST || (JUCE_PLUGINHOST_LADSPA && (JUCE_LINUX || JUCE_BSD))\r
 \r
 static bool arrayContainsPlugin (const OwnedArray<PluginDescription>& list,\r
                                  const PluginDescription& desc)\r
@@ -220,6 +220,7 @@ private:
 #include "utilities/juce_AudioProcessorValueTreeState.cpp"\r
 #include "utilities/juce_PluginHostType.cpp"\r
 #include "utilities/juce_NativeScaleFactorNotifier.cpp"\r
+#include "utilities/juce_VSTCallbackHandler.cpp"\r
 #include "utilities/ARA/juce_ARA_utils.cpp"\r
 \r
 #include "format_types/juce_LV2PluginFormat.cpp"\r
index bf9b568d0b5dcc8cf8eaaf5d9543474391f68d42..aa618eeb712bc8a625b8ea598fb9e194724a6fac 100644 (file)
 \r
   ID:                 juce_audio_processors\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE audio processor classes\r
   description:        Classes for loading and playing VST, AU, LADSPA, or internally-generated audio processors.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_gui_extra, juce_audio_basics\r
   OSXFrameworks:      CoreAudio CoreMIDI AudioToolbox\r
index 53aa9c3d83fa6a30f091658bb2f51241744fd3b4..f5815241ec080dc7e305815b91cc75de5193f95e 100644 (file)
@@ -340,7 +340,7 @@ void AudioProcessor::removeListener (AudioProcessorListener* listenerToRemove)
 \r
 void AudioProcessor::setPlayConfigDetails (int newNumIns, int newNumOuts, double newSampleRate, int newBlockSize)\r
 {\r
-    bool success = true;\r
+    [[maybe_unused]] bool success = true;\r
 \r
     if (getTotalNumInputChannels() != newNumIns)\r
         success &= setChannelLayoutOfBus (true,  0, AudioChannelSet::canonicalChannelSet (newNumIns));\r
@@ -362,7 +362,6 @@ void AudioProcessor::setPlayConfigDetails (int newNumIns, int newNumOuts, double
     jassert (success && newNumIns == getTotalNumInputChannels() && newNumOuts == getTotalNumOutputChannels());\r
 \r
     setRateAndBufferSizeDetails (newSampleRate, newBlockSize);\r
-    ignoreUnused (success);\r
 }\r
 \r
 void AudioProcessor::setRateAndBufferSizeDetails (double newSampleRate, int newBlockSize) noexcept\r
@@ -442,10 +441,8 @@ void AudioProcessor::validateParameter (AudioProcessorParameter* param)
    #endif\r
 }\r
 \r
-void AudioProcessor::checkForDuplicateTrimmedParamID (AudioProcessorParameter* param)\r
+void AudioProcessor::checkForDuplicateTrimmedParamID ([[maybe_unused]] AudioProcessorParameter* param)\r
 {\r
-    ignoreUnused (param);\r
-\r
    #if JUCE_DEBUG && ! JUCE_DISABLE_CAUTIOUS_PARAMETER_ID_CHECKING\r
     if (auto* withID = dynamic_cast<AudioProcessorParameterWithID*> (param))\r
     {\r
@@ -476,10 +473,8 @@ void AudioProcessor::checkForDuplicateTrimmedParamID (AudioProcessorParameter* p
    #endif\r
 }\r
 \r
-void AudioProcessor::checkForDuplicateParamID (AudioProcessorParameter* param)\r
+void AudioProcessor::checkForDuplicateParamID ([[maybe_unused]] AudioProcessorParameter* param)\r
 {\r
-    ignoreUnused (param);\r
-\r
    #if JUCE_DEBUG\r
     if (auto* withID = dynamic_cast<AudioProcessorParameterWithID*> (param))\r
     {\r
@@ -491,10 +486,8 @@ void AudioProcessor::checkForDuplicateParamID (AudioProcessorParameter* param)
    #endif\r
 }\r
 \r
-void AudioProcessor::checkForDuplicateGroupIDs (const AudioProcessorParameterGroup& newGroup)\r
+void AudioProcessor::checkForDuplicateGroupIDs ([[maybe_unused]] const AudioProcessorParameterGroup& newGroup)\r
 {\r
-    ignoreUnused (newGroup);\r
-\r
    #if JUCE_DEBUG\r
     auto groups = newGroup.getSubgroups (true);\r
     groups.add (&newGroup);\r
@@ -598,10 +591,9 @@ void AudioProcessor::processBypassed (AudioBuffer<floatType>& buffer, MidiBuffer
 void AudioProcessor::processBlockBypassed (AudioBuffer<float>&  buffer, MidiBuffer& midi)    { processBypassed (buffer, midi); }\r
 void AudioProcessor::processBlockBypassed (AudioBuffer<double>& buffer, MidiBuffer& midi)    { processBypassed (buffer, midi); }\r
 \r
-void AudioProcessor::processBlock (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)\r
+void AudioProcessor::processBlock ([[maybe_unused]] AudioBuffer<double>& buffer,\r
+                                   [[maybe_unused]] MidiBuffer& midiMessages)\r
 {\r
-    ignoreUnused (buffer, midiMessages);\r
-\r
     // If you hit this assertion then either the caller called the double\r
     // precision version of processBlock on a processor which does not support it\r
     // (i.e. supportsDoublePrecisionProcessing() returns false), or the implementation\r
@@ -1493,6 +1485,9 @@ AudioProcessorParameter* AudioProcessor::getParamChecked (int index) const
     return p;\r
 }\r
 \r
+bool AudioProcessor::canAddBus ([[maybe_unused]] bool isInput) const                     { return false; }\r
+bool AudioProcessor::canRemoveBus ([[maybe_unused]] bool isInput) const                  { return false; }\r
+\r
 JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
 JUCE_END_IGNORE_WARNINGS_MSVC\r
 \r
index 36e9769f22bd18c90b6508de6d9fe43cb007fa60..b0acefa927340f8eba4bd042df6efc49b63d6851 100644 (file)
@@ -418,7 +418,7 @@ public:
             @param set           The AudioChannelSet which is to be probed.\r
             @param currentLayout If non-null, pretend that the current layout of the AudioProcessor is\r
                                  currentLayout. On exit, currentLayout will be modified to\r
-                                 to represent the buses layouts of the AudioProcessor as if the layout\r
+                                 represent the buses layouts of the AudioProcessor as if the layout\r
                                  of the receiver had been successfully changed. This is useful as changing\r
                                  the layout of the receiver may change the bus layout of other buses.\r
 \r
@@ -524,7 +524,7 @@ public:
 \r
          @see addBus\r
     */\r
-    virtual bool canAddBus (bool isInput) const                     { ignoreUnused (isInput); return false; }\r
+    virtual bool canAddBus (bool isInput) const;\r
 \r
     /**  Callback to query if the last bus can currently be removed.\r
 \r
@@ -537,7 +537,7 @@ public:
 \r
          The default implementation will always return false.\r
     */\r
-    virtual bool canRemoveBus (bool isInput) const                  { ignoreUnused (isInput); return false; }\r
+    virtual bool canRemoveBus (bool isInput) const;\r
 \r
     /** Dynamically request an additional bus.\r
 \r
@@ -1361,8 +1361,8 @@ protected:
 \r
         void addBus (bool isInput, const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true);\r
 \r
-        JUCE_NODISCARD BusesProperties withInput  (const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true) const;\r
-        JUCE_NODISCARD BusesProperties withOutput (const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true) const;\r
+        [[nodiscard]] BusesProperties withInput  (const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true) const;\r
+        [[nodiscard]] BusesProperties withOutput (const String& name, const AudioChannelSet& defaultLayout, bool isActivatedByDefault = true) const;\r
     };\r
 \r
     /** Callback to query if adding/removing buses currently possible.\r
index 3b88ccee001ed552731853196bfb25fc62c7d340..7b20407cca61e129da4f1adbe786eeafb001ada9 100644 (file)
@@ -216,13 +216,11 @@ void AudioProcessorEditor::setScaleFactor (float newScale)
 typedef ComponentPeer* (*createUnityPeerFunctionType) (Component&);\r
 createUnityPeerFunctionType juce_createUnityPeerFn = nullptr;\r
 \r
-ComponentPeer* AudioProcessorEditor::createNewPeer (int styleFlags, void* nativeWindow)\r
+ComponentPeer* AudioProcessorEditor::createNewPeer ([[maybe_unused]] int styleFlags,\r
+                                                    [[maybe_unused]] void* nativeWindow)\r
 {\r
     if (juce_createUnityPeerFn != nullptr)\r
-    {\r
-        ignoreUnused (styleFlags, nativeWindow);\r
         return juce_createUnityPeerFn (*this);\r
-    }\r
 \r
     return Component::createNewPeer (styleFlags, nativeWindow);\r
 }\r
index ea943564b0124f89b3a2666edf8aa235a0a249c7..5e615433abcd1d8b20b88a8f2ae821b258e62376 100644 (file)
   ==============================================================================\r
 */\r
 \r
+// Implementation notes:\r
+// On macOS, calling AudioUnitInitialize will internally call AudioObjectGetPropertyData, which\r
+// takes a mutex.\r
+// This same mutex is taken on the audio thread, before calling the audio device's IO callback.\r
+// This is a property of the CoreAudio implementation - we can't remove or interact directly\r
+// with these locks in JUCE.\r
+//\r
+// AudioProcessor instances expect that their callback lock will be taken before calling\r
+// processBlock or processBlockBypassed.\r
+// This means that, to avoid deadlocks, we *always* need to make sure that the CoreAudio mutex\r
+// is locked before taking the callback lock.\r
+// Given that we can't interact with the CoreAudio mutex directly, on the main thread we can't\r
+// call any function that might internally interact with CoreAudio while the callback lock is\r
+// taken.\r
+// In particular, be careful not to call `prepareToPlay` on a hosted AudioUnit from the main\r
+// thread while the callback lock is taken.\r
+// The graph implementation currently makes sure to call prepareToPlay on the main thread,\r
+// without taking the graph's callback lock.\r
+\r
 namespace juce\r
 {\r
 \r
-static void updateOnMessageThread (AsyncUpdater& updater)\r
+/*  Provides a comparison function for various types that have an associated NodeID,\r
+    for use with equal_range, lower_bound etc.\r
+*/\r
+class ImplicitNode\r
 {\r
-    if (MessageManager::getInstance()->isThisTheMessageThread())\r
-        updater.handleAsyncUpdate();\r
-    else\r
-        updater.triggerAsyncUpdate();\r
-}\r
+public:\r
+    using Node           = AudioProcessorGraph::Node;\r
+    using NodeID         = AudioProcessorGraph::NodeID;\r
+    using NodeAndChannel = AudioProcessorGraph::NodeAndChannel;\r
+\r
+    ImplicitNode (NodeID x) : node (x) {}\r
+    ImplicitNode (NodeAndChannel x) : ImplicitNode (x.nodeID) {}\r
+    ImplicitNode (const Node* x) : ImplicitNode (x->nodeID) {}\r
+    ImplicitNode (const std::pair<const NodeAndChannel, std::set<NodeAndChannel>>& x) : ImplicitNode (x.first) {}\r
+\r
+    /*  This is the comparison function. */\r
+    static bool compare (ImplicitNode a, ImplicitNode b) { return a.node < b.node; }\r
+\r
+private:\r
+    NodeID node;\r
+};\r
+\r
+//==============================================================================\r
+/*  A copyable type holding all the nodes, and allowing fast lookup by id. */\r
+class Nodes\r
+{\r
+public:\r
+    using Node           = AudioProcessorGraph::Node;\r
+    using NodeID         = AudioProcessorGraph::NodeID;\r
+\r
+    const ReferenceCountedArray<Node>& getNodes() const { return array; }\r
+\r
+    Node::Ptr getNodeForId (NodeID nodeID) const\r
+    {\r
+        const auto iter = std::lower_bound (array.begin(), array.end(), nodeID, ImplicitNode::compare);\r
+        return iter != array.end() && (*iter)->nodeID == nodeID ? *iter : nullptr;\r
+    }\r
+\r
+    Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor, const NodeID nodeID)\r
+    {\r
+        if (newProcessor == nullptr)\r
+        {\r
+            // Cannot add a null audio processor!\r
+            jassertfalse;\r
+            return {};\r
+        }\r
+\r
+        if (std::any_of (array.begin(),\r
+                         array.end(),\r
+                         [&] (auto* n) { return n->getProcessor() == newProcessor.get(); }))\r
+        {\r
+            // This audio processor has already been added to the graph!\r
+            jassertfalse;\r
+            return {};\r
+        }\r
+\r
+        const auto iter = std::lower_bound (array.begin(), array.end(), nodeID, ImplicitNode::compare);\r
+\r
+        if (iter != array.end() && (*iter)->nodeID == nodeID)\r
+        {\r
+            // This nodeID has already been used for a node in the graph!\r
+            jassertfalse;\r
+            return {};\r
+        }\r
+\r
+        return array.insert ((int) std::distance (array.begin(), iter),\r
+                             new Node { nodeID, std::move (newProcessor) });\r
+    }\r
+\r
+    Node::Ptr removeNode (NodeID nodeID)\r
+    {\r
+        const auto iter = std::lower_bound (array.begin(), array.end(), nodeID, ImplicitNode::compare);\r
+        return iter != array.end() && (*iter)->nodeID == nodeID\r
+             ? array.removeAndReturn ((int) std::distance (array.begin(), iter))\r
+             : nullptr;\r
+    }\r
+\r
+    bool operator== (const Nodes& other) const { return array == other.array; }\r
+    bool operator!= (const Nodes& other) const { return array != other.array; }\r
+\r
+private:\r
+    ReferenceCountedArray<Node> array;\r
+};\r
+\r
+//==============================================================================\r
+/*  A value type holding a full set of graph connections. */\r
+class Connections\r
+{\r
+public:\r
+    using Node           = AudioProcessorGraph::Node;\r
+    using NodeID         = AudioProcessorGraph::NodeID;\r
+    using Connection     = AudioProcessorGraph::Connection;\r
+    using NodeAndChannel = AudioProcessorGraph::NodeAndChannel;\r
+\r
+    static constexpr auto midiChannelIndex = AudioProcessorGraph::midiChannelIndex;\r
+\r
+    bool addConnection (const Nodes& n, const Connection& c)\r
+    {\r
+        if (! canConnect (n, c))\r
+            return false;\r
+\r
+        sourcesForDestination[c.destination].insert (c.source);\r
+        jassert (isConnected (c));\r
+        return true;\r
+    }\r
+\r
+    bool removeConnection (const Connection& c)\r
+    {\r
+        const auto iter = sourcesForDestination.find (c.destination);\r
+        return iter != sourcesForDestination.cend() && iter->second.erase (c.source) == 1;\r
+    }\r
+\r
+    bool removeIllegalConnections (const Nodes& n)\r
+    {\r
+        auto anyRemoved = false;\r
+\r
+        for (auto& dest : sourcesForDestination)\r
+        {\r
+            const auto initialSize = dest.second.size();\r
+            dest.second = removeIllegalConnections (n, std::move (dest.second), dest.first);\r
+            anyRemoved |= (dest.second.size() != initialSize);\r
+        }\r
+\r
+        return anyRemoved;\r
+    }\r
+\r
+    bool disconnectNode (NodeID n)\r
+    {\r
+        const auto matchingDestinations = getMatchingDestinations (n);\r
+        auto result = matchingDestinations.first != matchingDestinations.second;\r
+        sourcesForDestination.erase (matchingDestinations.first, matchingDestinations.second);\r
+\r
+        for (auto& pair : sourcesForDestination)\r
+        {\r
+            const auto range = std::equal_range (pair.second.cbegin(), pair.second.cend(), n, ImplicitNode::compare);\r
+            result |= range.first != range.second;\r
+            pair.second.erase (range.first, range.second);\r
+        }\r
+\r
+        return result;\r
+    }\r
+\r
+    static bool isConnectionLegal (const Nodes& n, Connection c)\r
+    {\r
+        const auto source = n.getNodeForId (c.source     .nodeID);\r
+        const auto dest   = n.getNodeForId (c.destination.nodeID);\r
+\r
+        const auto sourceChannel = c.source     .channelIndex;\r
+        const auto destChannel   = c.destination.channelIndex;\r
+\r
+        const auto sourceIsMIDI = AudioProcessorGraph::midiChannelIndex == sourceChannel;\r
+        const auto destIsMIDI   = AudioProcessorGraph::midiChannelIndex == destChannel;\r
+\r
+        return sourceChannel >= 0\r
+            && destChannel >= 0\r
+            && source != dest\r
+            && sourceIsMIDI == destIsMIDI\r
+            && source != nullptr\r
+            && (sourceIsMIDI\r
+                    ? source->getProcessor()->producesMidi()\r
+                    : sourceChannel < source->getProcessor()->getTotalNumOutputChannels())\r
+            && dest != nullptr\r
+            && (destIsMIDI\r
+                    ? dest->getProcessor()->acceptsMidi()\r
+                    : destChannel < dest->getProcessor()->getTotalNumInputChannels());\r
+    }\r
+\r
+    bool canConnect (const Nodes& n, Connection c) const\r
+    {\r
+        return isConnectionLegal (n, c) && ! isConnected (c);\r
+    }\r
+\r
+    bool isConnected (Connection c) const\r
+    {\r
+        const auto iter = sourcesForDestination.find (c.destination);\r
+\r
+        return iter != sourcesForDestination.cend()\r
+               && iter->second.find (c.source) != iter->second.cend();\r
+    }\r
+\r
+    bool isConnected (NodeID srcID, NodeID destID) const\r
+    {\r
+        const auto matchingDestinations = getMatchingDestinations (destID);\r
+\r
+        return std::any_of (matchingDestinations.first, matchingDestinations.second, [srcID] (const auto& pair)\r
+        {\r
+            const auto iter = std::lower_bound (pair.second.cbegin(), pair.second.cend(), srcID, ImplicitNode::compare);\r
+            return iter != pair.second.cend() && iter->nodeID == srcID;\r
+        });\r
+    }\r
+\r
+    std::set<NodeID> getSourceNodesForDestination (NodeID destID) const\r
+    {\r
+        const auto matchingDestinations = getMatchingDestinations (destID);\r
+\r
+        std::set<NodeID> result;\r
+        std::for_each (matchingDestinations.first, matchingDestinations.second, [&] (const auto& pair)\r
+        {\r
+            for (const auto& source : pair.second)\r
+                result.insert (source.nodeID);\r
+        });\r
+        return result;\r
+    }\r
+\r
+    std::set<NodeAndChannel> getSourcesForDestination (const NodeAndChannel& p) const\r
+    {\r
+        const auto iter = sourcesForDestination.find (p);\r
+        return iter != sourcesForDestination.cend() ? iter->second : std::set<NodeAndChannel>{};\r
+    }\r
+\r
+    std::vector<Connection> getConnections() const\r
+    {\r
+        std::vector<Connection> result;\r
+\r
+        for (auto& pair : sourcesForDestination)\r
+            for (const auto& source : pair.second)\r
+                result.emplace_back (source, pair.first);\r
+\r
+        std::sort (result.begin(), result.end());\r
+        result.erase (std::unique (result.begin(), result.end()), result.end());\r
+        return result;\r
+    }\r
+\r
+    bool isAnInputTo (NodeID source, NodeID dest) const\r
+    {\r
+        return getConnectedRecursive (source, dest, {}).found;\r
+    }\r
+\r
+    bool operator== (const Connections& other) const { return sourcesForDestination == other.sourcesForDestination; }\r
+    bool operator!= (const Connections& other) const { return sourcesForDestination != other.sourcesForDestination; }\r
+\r
+private:\r
+    using Map = std::map<NodeAndChannel, std::set<NodeAndChannel>>;\r
+\r
+    struct SearchState\r
+    {\r
+        std::set<NodeID> visited;\r
+        bool found = false;\r
+    };\r
+\r
+    SearchState getConnectedRecursive (NodeID source, NodeID dest, SearchState state) const\r
+    {\r
+        state.visited.insert (dest);\r
+\r
+        for (const auto& s : getSourceNodesForDestination (dest))\r
+        {\r
+            if (state.found || s == source)\r
+                return { std::move (state.visited), true };\r
+\r
+            if (state.visited.find (s) == state.visited.cend())\r
+                state = getConnectedRecursive (source, s, std::move (state));\r
+        }\r
+\r
+        return state;\r
+    }\r
+\r
+    static std::set<NodeAndChannel> removeIllegalConnections (const Nodes& nodes,\r
+                                                              std::set<NodeAndChannel> sources,\r
+                                                              NodeAndChannel destination)\r
+    {\r
+        for (auto source = sources.cbegin(); source != sources.cend();)\r
+        {\r
+            if (! isConnectionLegal (nodes, { *source, destination }))\r
+                source = sources.erase (source);\r
+            else\r
+                ++source;\r
+        }\r
+\r
+        return sources;\r
+    }\r
+\r
+    std::pair<Map::const_iterator, Map::const_iterator> getMatchingDestinations (NodeID destID) const\r
+    {\r
+        return std::equal_range (sourcesForDestination.cbegin(), sourcesForDestination.cend(), destID, ImplicitNode::compare);\r
+    }\r
+\r
+    Map sourcesForDestination;\r
+};\r
+\r
+//==============================================================================\r
+/*  Settings used to prepare a node for playback. */\r
+struct PrepareSettings\r
+{\r
+    using ProcessingPrecision = AudioProcessorGraph::ProcessingPrecision;\r
+\r
+    ProcessingPrecision precision = ProcessingPrecision::singlePrecision;\r
+    double sampleRate             = 0.0;\r
+    int blockSize                 = 0;\r
+\r
+    auto tie() const noexcept { return std::tie (precision, sampleRate, blockSize); }\r
+\r
+    bool operator== (const PrepareSettings& other) const { return tie() == other.tie(); }\r
+    bool operator!= (const PrepareSettings& other) const { return tie() != other.tie(); }\r
+};\r
+\r
+//==============================================================================\r
+/*  Keeps track of the PrepareSettings applied to each node. */\r
+class NodeStates\r
+{\r
+public:\r
+    using Node           = AudioProcessorGraph::Node;\r
+    using NodeID         = AudioProcessorGraph::NodeID;\r
+\r
+    /*  Called from prepareToPlay and releaseResources with the PrepareSettings that should be\r
+        used next time the graph is rebuilt.\r
+    */\r
+    void setState (Optional<PrepareSettings> newSettings)\r
+    {\r
+        const std::lock_guard<std::mutex> lock (mutex);\r
+        next = newSettings;\r
+    }\r
+\r
+    /*  Call from the audio thread only. */\r
+    Optional<PrepareSettings> getLastRequestedSettings() const { return next; }\r
+\r
+    /*  Call from the main thread only!\r
+\r
+        Called after updating the graph topology to prepare any currently-unprepared nodes.\r
+\r
+        To ensure that all nodes are initialised with the same sample rate, buffer size, etc. as\r
+        the enclosing graph, we must ensure that any operation that uses these details (preparing\r
+        individual nodes) is synchronized with prepare-to-play and release-resources on the\r
+        enclosing graph.\r
+\r
+        If the new PrepareSettings are different to the last-seen settings, all nodes will\r
+        be prepared/unprepared as necessary. If the PrepareSettings have not changed, then only\r
+        new nodes will be prepared/unprepared.\r
+\r
+        Returns the settings that were applied to the nodes.\r
+    */\r
+    Optional<PrepareSettings> applySettings (const Nodes& n)\r
+    {\r
+        const auto settingsChanged = [this]\r
+        {\r
+            const std::lock_guard<std::mutex> lock (mutex);\r
+            const auto result = current != next;\r
+            current = next;\r
+            return result;\r
+        }();\r
+\r
+        // It may look like releaseResources and prepareToPlay could race with calls to processBlock\r
+        // here, because applySettings is called from the main thread, processBlock is called from\r
+        // the audio thread (normally), and there's no explicit mutex ensuring that the calls don't\r
+        // overlap.\r
+        // However, it is part of the AudioProcessor contract that users shall not call\r
+        // processBlock, prepareToPlay, and/or releaseResources concurrently. That is, there's an\r
+        // implied mutex synchronising these functions on each AudioProcessor.\r
+        //\r
+        // Inside processBlock, we always ensure that the current RenderSequence's PrepareSettings\r
+        // match the graph's settings before attempting to call processBlock on any of the graph\r
+        // nodes; as a result, it's impossible to start calling processBlock on a node on the audio\r
+        // thread while a render sequence rebuild (including prepareToPlay/releaseResources calls)\r
+        // is already in progress here.\r
+        //\r
+        // Due to the implied mutex between prepareToPlay/releaseResources/processBlock, it's also\r
+        // impossible to receive new PrepareSettings and to start a new RenderSequence rebuild while\r
+        // a processBlock call is in progress.\r
+\r
+        if (settingsChanged)\r
+        {\r
+            for (const auto& node : n.getNodes())\r
+                node->getProcessor()->releaseResources();\r
+\r
+            preparedNodes.clear();\r
+        }\r
+\r
+        if (current.hasValue())\r
+        {\r
+            for (const auto& node : n.getNodes())\r
+            {\r
+                if (preparedNodes.find (node->nodeID) != preparedNodes.cend())\r
+                    continue;\r
+\r
+                preparedNodes.insert (node->nodeID);\r
 \r
+                node->getProcessor()->setProcessingPrecision (node->getProcessor()->supportsDoublePrecisionProcessing() ? current->precision\r
+                                                                                                                        : AudioProcessor::singlePrecision);\r
+                node->getProcessor()->setRateAndBufferSizeDetails (current->sampleRate, current->blockSize);\r
+                node->getProcessor()->prepareToPlay               (current->sampleRate, current->blockSize);\r
+            }\r
+        }\r
+\r
+        return current;\r
+    }\r
+\r
+private:\r
+    std::mutex mutex;\r
+    std::set<NodeID> preparedNodes;\r
+    Optional<PrepareSettings> current, next;\r
+};\r
+\r
+//==============================================================================\r
 template <typename FloatType>\r
 struct GraphRenderSequence\r
 {\r
+    using Node = AudioProcessorGraph::Node;\r
+\r
     struct Context\r
     {\r
-        FloatType** audioBuffers;\r
-        MidiBuffer* midiBuffers;\r
         AudioPlayHead* audioPlayHead;\r
         int numSamples;\r
     };\r
@@ -79,10 +482,10 @@ struct GraphRenderSequence
         currentMidiOutputBuffer.clear();\r
 \r
         {\r
-            const Context context { renderingBuffer.getArrayOfWritePointers(), midiBuffers.begin(), audioPlayHead, numSamples };\r
+            const Context context { audioPlayHead, numSamples };\r
 \r
-            for (auto* op : renderOps)\r
-                op->perform (context);\r
+            for (const auto& op : renderOps)\r
+                op->process (context);\r
         }\r
 \r
         for (int i = 0; i < buffer.getNumChannels(); ++i)\r
@@ -93,50 +496,201 @@ struct GraphRenderSequence
         currentAudioInputBuffer = nullptr;\r
     }\r
 \r
+    JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4661)\r
+\r
     void addClearChannelOp (int index)\r
     {\r
-        createOp ([=] (const Context& c)    { FloatVectorOperations::clear (c.audioBuffers[index], c.numSamples); });\r
+        struct ClearOp : public RenderOp\r
+        {\r
+            explicit ClearOp (int indexIn) : index (indexIn) {}\r
+\r
+            void prepare (FloatType* const* renderBuffer, MidiBuffer*) override\r
+            {\r
+                channelBuffer = renderBuffer[index];\r
+            }\r
+\r
+            void process (const Context& c) override\r
+            {\r
+                FloatVectorOperations::clear (channelBuffer, c.numSamples);\r
+            }\r
+\r
+            FloatType* channelBuffer = nullptr;\r
+            int index = 0;\r
+        };\r
+\r
+        renderOps.push_back (std::make_unique<ClearOp> (index));\r
     }\r
 \r
     void addCopyChannelOp (int srcIndex, int dstIndex)\r
     {\r
-        createOp ([=] (const Context& c)    { FloatVectorOperations::copy (c.audioBuffers[dstIndex],\r
-                                                                           c.audioBuffers[srcIndex],\r
-                                                                           c.numSamples); });\r
+        struct CopyOp : public RenderOp\r
+        {\r
+            explicit CopyOp (int fromIn, int toIn) : from (fromIn), to (toIn) {}\r
+\r
+            void prepare (FloatType* const* renderBuffer, MidiBuffer*) override\r
+            {\r
+                fromBuffer = renderBuffer[from];\r
+                toBuffer = renderBuffer[to];\r
+            }\r
+\r
+            void process (const Context& c) override\r
+            {\r
+                FloatVectorOperations::copy (toBuffer, fromBuffer, c.numSamples);\r
+            }\r
+\r
+            FloatType* fromBuffer = nullptr;\r
+            FloatType* toBuffer = nullptr;\r
+            int from = 0, to = 0;\r
+        };\r
+\r
+        renderOps.push_back (std::make_unique<CopyOp> (srcIndex, dstIndex));\r
     }\r
 \r
     void addAddChannelOp (int srcIndex, int dstIndex)\r
     {\r
-        createOp ([=] (const Context& c)    { FloatVectorOperations::add (c.audioBuffers[dstIndex],\r
-                                                                          c.audioBuffers[srcIndex],\r
-                                                                          c.numSamples); });\r
+        struct AddOp : public RenderOp\r
+        {\r
+            explicit AddOp (int fromIn, int toIn) : from (fromIn), to (toIn) {}\r
+\r
+            void prepare (FloatType* const* renderBuffer, MidiBuffer*) override\r
+            {\r
+                fromBuffer = renderBuffer[from];\r
+                toBuffer = renderBuffer[to];\r
+            }\r
+\r
+            void process (const Context& c) override\r
+            {\r
+                FloatVectorOperations::add (toBuffer, fromBuffer, c.numSamples);\r
+            }\r
+\r
+            FloatType* fromBuffer = nullptr;\r
+            FloatType* toBuffer = nullptr;\r
+            int from = 0, to = 0;\r
+        };\r
+\r
+        renderOps.push_back (std::make_unique<AddOp> (srcIndex, dstIndex));\r
     }\r
 \r
+    JUCE_END_IGNORE_WARNINGS_MSVC\r
+\r
     void addClearMidiBufferOp (int index)\r
     {\r
-        createOp ([=] (const Context& c)    { c.midiBuffers[index].clear(); });\r
+        struct ClearOp : public RenderOp\r
+        {\r
+            explicit ClearOp (int indexIn) : index (indexIn) {}\r
+\r
+            void prepare (FloatType* const*, MidiBuffer* buffers) override\r
+            {\r
+                channelBuffer = buffers + index;\r
+            }\r
+\r
+            void process (const Context&) override\r
+            {\r
+                channelBuffer->clear();\r
+            }\r
+\r
+            MidiBuffer* channelBuffer = nullptr;\r
+            int index = 0;\r
+        };\r
+\r
+        renderOps.push_back (std::make_unique<ClearOp> (index));\r
     }\r
 \r
     void addCopyMidiBufferOp (int srcIndex, int dstIndex)\r
     {\r
-        createOp ([=] (const Context& c)    { c.midiBuffers[dstIndex] = c.midiBuffers[srcIndex]; });\r
+        struct CopyOp : public RenderOp\r
+        {\r
+            explicit CopyOp (int fromIn, int toIn) : from (fromIn), to (toIn) {}\r
+\r
+            void prepare (FloatType* const*, MidiBuffer* buffers) override\r
+            {\r
+                fromBuffer = buffers + from;\r
+                toBuffer = buffers + to;\r
+            }\r
+\r
+            void process (const Context&) override\r
+            {\r
+                *toBuffer = *fromBuffer;\r
+            }\r
+\r
+            MidiBuffer* fromBuffer = nullptr;\r
+            MidiBuffer* toBuffer = nullptr;\r
+            int from = 0, to = 0;\r
+        };\r
+\r
+        renderOps.push_back (std::make_unique<CopyOp> (srcIndex, dstIndex));\r
     }\r
 \r
     void addAddMidiBufferOp (int srcIndex, int dstIndex)\r
     {\r
-        createOp ([=] (const Context& c)    { c.midiBuffers[dstIndex].addEvents (c.midiBuffers[srcIndex],\r
-                                                                                 0, c.numSamples, 0); });\r
+        struct AddOp : public RenderOp\r
+        {\r
+            explicit AddOp (int fromIn, int toIn) : from (fromIn), to (toIn) {}\r
+\r
+            void prepare (FloatType* const*, MidiBuffer* buffers) override\r
+            {\r
+                fromBuffer = buffers + from;\r
+                toBuffer = buffers + to;\r
+            }\r
+\r
+            void process (const Context& c) override\r
+            {\r
+                toBuffer->addEvents (*fromBuffer, 0, c.numSamples, 0);\r
+            }\r
+\r
+            MidiBuffer* fromBuffer = nullptr;\r
+            MidiBuffer* toBuffer = nullptr;\r
+            int from = 0, to = 0;\r
+        };\r
+\r
+        renderOps.push_back (std::make_unique<AddOp> (srcIndex, dstIndex));\r
     }\r
 \r
     void addDelayChannelOp (int chan, int delaySize)\r
     {\r
-        renderOps.add (new DelayChannelOp (chan, delaySize));\r
+        struct DelayChannelOp : public RenderOp\r
+        {\r
+            DelayChannelOp (int chan, int delaySize)\r
+                : buffer ((size_t) (delaySize + 1), (FloatType) 0),\r
+                  channel (chan),\r
+                  writeIndex (delaySize)\r
+            {\r
+            }\r
+\r
+            void prepare (FloatType* const* renderBuffer, MidiBuffer*) override\r
+            {\r
+                channelBuffer = renderBuffer[channel];\r
+            }\r
+\r
+            void process (const Context& c) override\r
+            {\r
+                auto* data = channelBuffer;\r
+\r
+                for (int i = c.numSamples; --i >= 0;)\r
+                {\r
+                    buffer[(size_t) writeIndex] = *data;\r
+                    *data++ = buffer[(size_t) readIndex];\r
+\r
+                    if (++readIndex  >= (int) buffer.size()) readIndex = 0;\r
+                    if (++writeIndex >= (int) buffer.size()) writeIndex = 0;\r
+                }\r
+            }\r
+\r
+            std::vector<FloatType> buffer;\r
+            FloatType* channelBuffer = nullptr;\r
+            const int channel;\r
+            int readIndex = 0, writeIndex;\r
+        };\r
+\r
+        renderOps.push_back (std::make_unique<DelayChannelOp> (chan, delaySize));\r
     }\r
 \r
-    void addProcessOp (const AudioProcessorGraph::Node::Ptr& node,\r
-                       const Array<int>& audioChannelsUsed, int totalNumChans, int midiBuffer)\r
+    void addProcessOp (const Node::Ptr& node,\r
+                       const Array<int>& audioChannelsUsed,\r
+                       int totalNumChans,\r
+                       int midiBuffer)\r
     {\r
-        renderOps.add (new ProcessOp (node, audioChannelsUsed, totalNumChans, midiBuffer));\r
+        renderOps.push_back (std::make_unique<ProcessOp> (node, audioChannelsUsed, totalNumChans, midiBuffer));\r
     }\r
 \r
     void prepareBuffers (int blockSize)\r
@@ -159,16 +713,9 @@ struct GraphRenderSequence
 \r
         for (auto&& m : midiBuffers)\r
             m.ensureSize (defaultMIDIBufferSize);\r
-    }\r
 \r
-    void releaseBuffers()\r
-    {\r
-        renderingBuffer.setSize (1, 1);\r
-        currentAudioOutputBuffer.setSize (1, 1);\r
-        currentAudioInputBuffer = nullptr;\r
-        currentMidiInputBuffer = nullptr;\r
-        currentMidiOutputBuffer.clear();\r
-        midiBuffers.clear();\r
+        for (const auto& op : renderOps)\r
+            op->prepare (renderingBuffer.getArrayOfWritePointers(), midiBuffers.data());\r
     }\r
 \r
     int numBuffersNeeded = 0, numMidiBuffersNeeded = 0;\r
@@ -184,89 +731,40 @@ struct GraphRenderSequence
 \r
 private:\r
     //==============================================================================\r
-    struct RenderingOp\r
-    {\r
-        RenderingOp() noexcept {}\r
-        virtual ~RenderingOp() {}\r
-        virtual void perform (const Context&) = 0;\r
-\r
-        JUCE_LEAK_DETECTOR (RenderingOp)\r
-    };\r
-\r
-    OwnedArray<RenderingOp> renderOps;\r
-\r
-    //==============================================================================\r
-    template <typename LambdaType,\r
-              std::enable_if_t<std::is_rvalue_reference<LambdaType&&>::value, int> = 0>\r
-    void createOp (LambdaType&& fn)\r
-    {\r
-        struct LambdaOp  : public RenderingOp\r
-        {\r
-            LambdaOp (LambdaType&& f) : function (std::forward<LambdaType> (f)) {}\r
-            void perform (const Context& c) override    { function (c); }\r
-\r
-            LambdaType function;\r
-        };\r
-\r
-        renderOps.add (new LambdaOp (std::forward<LambdaType> (fn)));\r
-    }\r
-\r
-    //==============================================================================\r
-    struct DelayChannelOp  : public RenderingOp\r
+    struct RenderOp\r
     {\r
-        DelayChannelOp (int chan, int delaySize)\r
-            : channel (chan),\r
-              bufferSize (delaySize + 1),\r
-              writeIndex (delaySize)\r
-        {\r
-            buffer.calloc ((size_t) bufferSize);\r
-        }\r
-\r
-        void perform (const Context& c) override\r
-        {\r
-            auto* data = c.audioBuffers[channel];\r
-\r
-            for (int i = c.numSamples; --i >= 0;)\r
-            {\r
-                buffer[writeIndex] = *data;\r
-                *data++ = buffer[readIndex];\r
-\r
-                if (++readIndex  >= bufferSize) readIndex = 0;\r
-                if (++writeIndex >= bufferSize) writeIndex = 0;\r
-            }\r
-        }\r
-\r
-        HeapBlock<FloatType> buffer;\r
-        const int channel, bufferSize;\r
-        int readIndex = 0, writeIndex;\r
-\r
-        JUCE_DECLARE_NON_COPYABLE (DelayChannelOp)\r
+        virtual ~RenderOp() = default;\r
+        virtual void prepare (FloatType* const*, MidiBuffer*) = 0;\r
+        virtual void process (const Context&) = 0;\r
     };\r
 \r
-    //==============================================================================\r
-    struct ProcessOp   : public RenderingOp\r
+    struct ProcessOp : public RenderOp\r
     {\r
-        ProcessOp (const AudioProcessorGraph::Node::Ptr& n,\r
+        ProcessOp (const Node::Ptr& n,\r
                    const Array<int>& audioChannelsUsed,\r
-                   int totalNumChans, int midiBuffer)\r
+                   int totalNumChans,\r
+                   int midiBufferIndex)\r
             : node (n),\r
               processor (*n->getProcessor()),\r
               audioChannelsToUse (audioChannelsUsed),\r
-              totalChans (jmax (1, totalNumChans)),\r
-              midiBufferToUse (midiBuffer)\r
+              audioChannels ((size_t) jmax (1, totalNumChans), nullptr),\r
+              midiBufferToUse (midiBufferIndex)\r
         {\r
-            audioChannels.calloc ((size_t) totalChans);\r
-\r
-            while (audioChannelsToUse.size() < totalChans)\r
+            while (audioChannelsToUse.size() < (int) audioChannels.size())\r
                 audioChannelsToUse.add (0);\r
         }\r
 \r
-        void perform (const Context& c) override\r
+        void prepare (FloatType* const* renderBuffer, MidiBuffer* buffers) override\r
         {\r
-            processor.setPlayHead (c.audioPlayHead);\r
+            for (size_t i = 0; i < audioChannels.size(); ++i)\r
+                audioChannels[i] = renderBuffer[audioChannelsToUse.getUnchecked ((int) i)];\r
 \r
-            for (int i = 0; i < totalChans; ++i)\r
-                audioChannels[i] = c.audioBuffers[audioChannelsToUse.getUnchecked (i)];\r
+            midiBuffer = buffers + midiBufferToUse;\r
+        }\r
+\r
+        void process (const Context& c) override\r
+        {\r
+            processor.setPlayHead (c.audioPlayHead);\r
 \r
             auto numAudioChannels = [this]\r
             {\r
@@ -274,111 +772,102 @@ private:
                     if (proc->getTotalNumInputChannels() == 0 && proc->getTotalNumOutputChannels() == 0)\r
                         return 0;\r
 \r
-                return totalChans;\r
+                return (int) audioChannels.size();\r
             }();\r
 \r
-            AudioBuffer<FloatType> buffer (audioChannels, numAudioChannels, c.numSamples);\r
+            AudioBuffer<FloatType> buffer { audioChannels.data(), numAudioChannels, c.numSamples };\r
 \r
             const ScopedLock lock (processor.getCallbackLock());\r
 \r
             if (processor.isSuspended())\r
                 buffer.clear();\r
             else\r
-                callProcess (buffer, c.midiBuffers[midiBufferToUse]);\r
+                callProcess (buffer, *midiBuffer);\r
         }\r
 \r
-        void callProcess (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)\r
+        void callProcess (AudioBuffer<float>& buffer, MidiBuffer& midi)\r
         {\r
             if (processor.isUsingDoublePrecision())\r
             {\r
                 tempBufferDouble.makeCopyOf (buffer, true);\r
-\r
-                if (node->isBypassed())\r
-                    node->processBlockBypassed (tempBufferDouble, midiMessages);\r
-                else\r
-                    node->processBlock (tempBufferDouble, midiMessages);\r
-\r
+                process (*node, tempBufferDouble, midi);\r
                 buffer.makeCopyOf (tempBufferDouble, true);\r
             }\r
             else\r
             {\r
-                if (node->isBypassed())\r
-                    node->processBlockBypassed (buffer, midiMessages);\r
-                else\r
-                    node->processBlock (buffer, midiMessages);\r
+                process (*node, buffer, midi);\r
             }\r
         }\r
 \r
-        void callProcess (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)\r
+        void callProcess (AudioBuffer<double>& buffer, MidiBuffer& midi)\r
         {\r
             if (processor.isUsingDoublePrecision())\r
             {\r
-                if (node->isBypassed())\r
-                    node->processBlockBypassed (buffer, midiMessages);\r
-                else\r
-                    node->processBlock (buffer, midiMessages);\r
+                process (*node, buffer, midi);\r
             }\r
             else\r
             {\r
                 tempBufferFloat.makeCopyOf (buffer, true);\r
-\r
-                if (node->isBypassed())\r
-                    node->processBlockBypassed (tempBufferFloat, midiMessages);\r
-                else\r
-                    node->processBlock (tempBufferFloat, midiMessages);\r
-\r
+                process (*node, tempBufferFloat, midi);\r
                 buffer.makeCopyOf (tempBufferFloat, true);\r
             }\r
         }\r
 \r
-        const AudioProcessorGraph::Node::Ptr node;\r
+        template <typename Value>\r
+        static void process (const Node& node, AudioBuffer<Value>& audio, MidiBuffer& midi)\r
+        {\r
+            if (node.isBypassed() && node.getProcessor()->getBypassParameter() == nullptr)\r
+                node.getProcessor()->processBlockBypassed (audio, midi);\r
+            else\r
+                node.getProcessor()->processBlock (audio, midi);\r
+        }\r
+\r
+        const Node::Ptr node;\r
         AudioProcessor& processor;\r
+        MidiBuffer* midiBuffer = nullptr;\r
 \r
         Array<int> audioChannelsToUse;\r
-        HeapBlock<FloatType*> audioChannels;\r
+        std::vector<FloatType*> audioChannels;\r
         AudioBuffer<float> tempBufferFloat, tempBufferDouble;\r
-        const int totalChans, midiBufferToUse;\r
-\r
-        JUCE_DECLARE_NON_COPYABLE (ProcessOp)\r
+        const int midiBufferToUse;\r
     };\r
+\r
+    std::vector<std::unique_ptr<RenderOp>> renderOps;\r
 };\r
 \r
 //==============================================================================\r
-//==============================================================================\r
-template <typename RenderSequence>\r
-struct RenderSequenceBuilder\r
+class RenderSequenceBuilder\r
 {\r
-    RenderSequenceBuilder (AudioProcessorGraph& g, RenderSequence& s)\r
-        : graph (g), sequence (s), orderedNodes (createOrderedNodeList (graph))\r
+public:\r
+    using Node           = AudioProcessorGraph::Node;\r
+    using NodeID         = AudioProcessorGraph::NodeID;\r
+    using Connection     = AudioProcessorGraph::Connection;\r
+    using NodeAndChannel = AudioProcessorGraph::NodeAndChannel;\r
+\r
+    static constexpr auto midiChannelIndex = AudioProcessorGraph::midiChannelIndex;\r
+\r
+    template <typename RenderSequence>\r
+    static auto build (const Nodes& n, const Connections& c)\r
     {\r
-        audioBuffers.add (AssignedBuffer::createReadOnlyEmpty()); // first buffer is read-only zeros\r
-        midiBuffers .add (AssignedBuffer::createReadOnlyEmpty());\r
+        RenderSequence sequence;\r
+        const RenderSequenceBuilder builder (n, c, sequence);\r
 \r
-        for (int i = 0; i < orderedNodes.size(); ++i)\r
+        struct SequenceAndLatency\r
         {\r
-            createRenderingOpsForNode (*orderedNodes.getUnchecked(i), i);\r
-            markAnyUnusedBuffersAsFree (audioBuffers, i);\r
-            markAnyUnusedBuffersAsFree (midiBuffers, i);\r
-        }\r
-\r
-        graph.setLatencySamples (totalLatency);\r
+            RenderSequence sequence;\r
+            int latencySamples = 0;\r
+        };\r
 \r
-        s.numBuffersNeeded = audioBuffers.size();\r
-        s.numMidiBuffersNeeded = midiBuffers.size();\r
+        return SequenceAndLatency { std::move (sequence), builder.totalLatency };\r
     }\r
 \r
+private:\r
     //==============================================================================\r
-    using Node = AudioProcessorGraph::Node;\r
-    using NodeID = AudioProcessorGraph::NodeID;\r
-\r
-    AudioProcessorGraph& graph;\r
-    RenderSequence& sequence;\r
-\r
     const Array<Node*> orderedNodes;\r
 \r
     struct AssignedBuffer\r
     {\r
-        AudioProcessorGraph::NodeAndChannel channel;\r
+        NodeAndChannel channel;\r
 \r
         static AssignedBuffer createReadOnlyEmpty() noexcept    { return { { zeroNodeID(), 0 } }; }\r
         static AssignedBuffer createFree() noexcept             { return { { freeNodeID(), 0 } }; }\r
@@ -400,12 +889,6 @@ struct RenderSequenceBuilder
 \r
     enum { readOnlyEmptyBufferIndex = 0 };\r
 \r
-    struct Delay\r
-    {\r
-        NodeID nodeID;\r
-        int delay;\r
-    };\r
-\r
     HashMap<uint32, int> delays;\r
     int totalLatency = 0;\r
 \r
@@ -414,32 +897,29 @@ struct RenderSequenceBuilder
         return delays[nodeID.uid];\r
     }\r
 \r
-    int getInputLatencyForNode (NodeID nodeID) const\r
+    int getInputLatencyForNode (const Connections& c, NodeID nodeID) const\r
     {\r
-        int maxLatency = 0;\r
-\r
-        for (auto&& c : graph.getConnections())\r
-            if (c.destination.nodeID == nodeID)\r
-                maxLatency = jmax (maxLatency, getNodeDelay (c.source.nodeID));\r
-\r
-        return maxLatency;\r
+        const auto sources = c.getSourceNodesForDestination (nodeID);\r
+        return std::accumulate (sources.cbegin(), sources.cend(), 0, [this] (auto acc, auto source)\r
+        {\r
+            return jmax (acc, this->getNodeDelay (source));\r
+        });\r
     }\r
 \r
     //==============================================================================\r
-    static void getAllParentsOfNode (const Node* child,\r
-                                     std::unordered_set<Node*>& parents,\r
-                                     const std::unordered_map<Node*, std::unordered_set<Node*>>& otherParents)\r
+    void getAllParentsOfNode (const NodeID& child,\r
+                              std::set<NodeID>& parents,\r
+                              const std::map<NodeID, std::set<NodeID>>& otherParents,\r
+                              const Connections& c)\r
     {\r
-        for (auto&& i : child->inputs)\r
+        for (const auto& parentNode : c.getSourceNodesForDestination (child))\r
         {\r
-            auto* parentNode = i.otherNode;\r
-\r
             if (parentNode == child)\r
                 continue;\r
 \r
             if (parents.insert (parentNode).second)\r
             {\r
-                auto parentParents = otherParents.find (parentNode);\r
+                const auto parentParents = otherParents.find (parentNode);\r
 \r
                 if (parentParents != otherParents.end())\r
                 {\r
@@ -447,46 +927,53 @@ struct RenderSequenceBuilder
                     continue;\r
                 }\r
 \r
-                getAllParentsOfNode (i.otherNode, parents, otherParents);\r
+                getAllParentsOfNode (parentNode, parents, otherParents, c);\r
             }\r
         }\r
     }\r
 \r
-    static auto createOrderedNodeList (const AudioProcessorGraph& graph)\r
+    Array<Node*> createOrderedNodeList (const Nodes& n, const Connections& c)\r
     {\r
         Array<Node*> result;\r
 \r
-        std::unordered_map<Node*, std::unordered_set<Node*>> nodeParents;\r
+        std::map<NodeID, std::set<NodeID>> nodeParents;\r
 \r
-        for (auto* node : graph.getNodes())\r
+        for (auto& node : n.getNodes())\r
         {\r
+            const auto nodeID = node->nodeID;\r
             int insertionIndex = 0;\r
 \r
             for (; insertionIndex < result.size(); ++insertionIndex)\r
             {\r
-                auto& parents = nodeParents[result.getUnchecked (insertionIndex)];\r
+                auto& parents = nodeParents[result.getUnchecked (insertionIndex)->nodeID];\r
 \r
-                if (parents.find (node) != parents.end())\r
+                if (parents.find (nodeID) != parents.end())\r
                     break;\r
             }\r
 \r
             result.insert (insertionIndex, node);\r
-            getAllParentsOfNode (node, nodeParents[node], nodeParents);\r
+            getAllParentsOfNode (nodeID, nodeParents[node->nodeID], nodeParents, c);\r
         }\r
 \r
         return result;\r
     }\r
 \r
-    int findBufferForInputAudioChannel (Node& node, const int inputChan,\r
-                                        const int ourRenderingIndex, const int maxLatency)\r
+    //==============================================================================\r
+    template <typename RenderSequence>\r
+    int findBufferForInputAudioChannel (const Connections& c,\r
+                                        RenderSequence& sequence,\r
+                                        Node& node,\r
+                                        const int inputChan,\r
+                                        const int ourRenderingIndex,\r
+                                        const int maxLatency)\r
     {\r
         auto& processor = *node.getProcessor();\r
         auto numOuts = processor.getTotalNumOutputChannels();\r
 \r
-        auto sources = getSourcesForChannel (node, inputChan);\r
+        auto sources = c.getSourcesForDestination ({ node.nodeID, inputChan });\r
 \r
         // Handle an unconnected input channel...\r
-        if (sources.isEmpty())\r
+        if (sources.empty())\r
         {\r
             if (inputChan >= numOuts)\r
                 return readOnlyEmptyBufferIndex;\r
@@ -500,7 +987,7 @@ struct RenderSequenceBuilder
         if (sources.size() == 1)\r
         {\r
             // channel with a straightforward single input..\r
-            auto src = sources.getUnchecked(0);\r
+            auto src = *sources.begin();\r
 \r
             int bufIndex = getBufferContaining (src);\r
 \r
@@ -511,8 +998,7 @@ struct RenderSequenceBuilder
                 jassert (bufIndex >= 0);\r
             }\r
 \r
-            if (inputChan < numOuts\r
-                 && isBufferNeededLater (ourRenderingIndex, inputChan, src))\r
+            if (inputChan < numOuts && isBufferNeededLater (c, ourRenderingIndex, inputChan, src))\r
             {\r
                 // can't mess up this channel because it's needed later by another node,\r
                 // so we need to use a copy of it..\r
@@ -533,23 +1019,27 @@ struct RenderSequenceBuilder
         int reusableInputIndex = -1;\r
         int bufIndex = -1;\r
 \r
-        for (int i = 0; i < sources.size(); ++i)\r
         {\r
-            auto src = sources.getReference(i);\r
-            auto sourceBufIndex = getBufferContaining (src);\r
-\r
-            if (sourceBufIndex >= 0 && ! isBufferNeededLater (ourRenderingIndex, inputChan, src))\r
+            auto i = 0;\r
+            for (const auto& src : sources)\r
             {\r
-                // we've found one of our input chans that can be re-used..\r
-                reusableInputIndex = i;\r
-                bufIndex = sourceBufIndex;\r
+                auto sourceBufIndex = getBufferContaining (src);\r
 \r
-                auto nodeDelay = getNodeDelay (src.nodeID);\r
+                if (sourceBufIndex >= 0 && ! isBufferNeededLater (c, ourRenderingIndex, inputChan, src))\r
+                {\r
+                    // we've found one of our input chans that can be re-used..\r
+                    reusableInputIndex = i;\r
+                    bufIndex = sourceBufIndex;\r
 \r
-                if (nodeDelay < maxLatency)\r
-                    sequence.addDelayChannelOp (bufIndex, maxLatency - nodeDelay);\r
+                    auto nodeDelay = getNodeDelay (src.nodeID);\r
 \r
-                break;\r
+                    if (nodeDelay < maxLatency)\r
+                        sequence.addDelayChannelOp (bufIndex, maxLatency - nodeDelay);\r
+\r
+                    break;\r
+                }\r
+\r
+                ++i;\r
             }\r
         }\r
 \r
@@ -561,7 +1051,7 @@ struct RenderSequenceBuilder
 \r
             audioBuffers.getReference (bufIndex).setAssignedToNonExistentNode();\r
 \r
-            auto srcIndex = getBufferContaining (sources.getFirst());\r
+            auto srcIndex = getBufferContaining (*sources.begin());\r
 \r
             if (srcIndex < 0)\r
                 sequence.addClearChannelOp (bufIndex);  // if not found, this is probably a feedback loop\r
@@ -569,53 +1059,61 @@ struct RenderSequenceBuilder
                 sequence.addCopyChannelOp (srcIndex, bufIndex);\r
 \r
             reusableInputIndex = 0;\r
-            auto nodeDelay = getNodeDelay (sources.getFirst().nodeID);\r
+            auto nodeDelay = getNodeDelay (sources.begin()->nodeID);\r
 \r
             if (nodeDelay < maxLatency)\r
                 sequence.addDelayChannelOp (bufIndex, maxLatency - nodeDelay);\r
         }\r
 \r
-        for (int i = 0; i < sources.size(); ++i)\r
         {\r
-            if (i != reusableInputIndex)\r
+            auto i = 0;\r
+            for (const auto& src : sources)\r
             {\r
-                auto src = sources.getReference(i);\r
-                int srcIndex = getBufferContaining (src);\r
-\r
-                if (srcIndex >= 0)\r
+                if (i != reusableInputIndex)\r
                 {\r
-                    auto nodeDelay = getNodeDelay (src.nodeID);\r
+                    int srcIndex = getBufferContaining (src);\r
 \r
-                    if (nodeDelay < maxLatency)\r
+                    if (srcIndex >= 0)\r
                     {\r
-                        if (! isBufferNeededLater (ourRenderingIndex, inputChan, src))\r
-                        {\r
-                            sequence.addDelayChannelOp (srcIndex, maxLatency - nodeDelay);\r
-                        }\r
-                        else // buffer is reused elsewhere, can't be delayed\r
+                        auto nodeDelay = getNodeDelay (src.nodeID);\r
+\r
+                        if (nodeDelay < maxLatency)\r
                         {\r
-                            auto bufferToDelay = getFreeBuffer (audioBuffers);\r
-                            sequence.addCopyChannelOp (srcIndex, bufferToDelay);\r
-                            sequence.addDelayChannelOp (bufferToDelay, maxLatency - nodeDelay);\r
-                            srcIndex = bufferToDelay;\r
+                            if (! isBufferNeededLater (c, ourRenderingIndex, inputChan, src))\r
+                            {\r
+                                sequence.addDelayChannelOp (srcIndex, maxLatency - nodeDelay);\r
+                            }\r
+                            else // buffer is reused elsewhere, can't be delayed\r
+                            {\r
+                                auto bufferToDelay = getFreeBuffer (audioBuffers);\r
+                                sequence.addCopyChannelOp (srcIndex, bufferToDelay);\r
+                                sequence.addDelayChannelOp (bufferToDelay, maxLatency - nodeDelay);\r
+                                srcIndex = bufferToDelay;\r
+                            }\r
                         }\r
-                    }\r
 \r
-                    sequence.addAddChannelOp (srcIndex, bufIndex);\r
+                        sequence.addAddChannelOp (srcIndex, bufIndex);\r
+                    }\r
                 }\r
+\r
+                ++i;\r
             }\r
         }\r
 \r
         return bufIndex;\r
     }\r
 \r
-    int findBufferForInputMidiChannel (Node& node, int ourRenderingIndex)\r
+    template <typename RenderSequence>\r
+    int findBufferForInputMidiChannel (const Connections& c,\r
+                                       RenderSequence& sequence,\r
+                                       Node& node,\r
+                                       int ourRenderingIndex)\r
     {\r
         auto& processor = *node.getProcessor();\r
-        auto sources = getSourcesForChannel (node, AudioProcessorGraph::midiChannelIndex);\r
+        auto sources = c.getSourcesForDestination ({ node.nodeID, midiChannelIndex });\r
 \r
         // No midi inputs..\r
-        if (sources.isEmpty())\r
+        if (sources.empty())\r
         {\r
             auto midiBufferToUse = getFreeBuffer (midiBuffers); // need to pick a buffer even if the processor doesn't use midi\r
 \r
@@ -628,12 +1126,12 @@ struct RenderSequenceBuilder
         // One midi input..\r
         if (sources.size() == 1)\r
         {\r
-            auto src = sources.getReference (0);\r
+            auto src = *sources.begin();\r
             auto midiBufferToUse = getBufferContaining (src);\r
 \r
             if (midiBufferToUse >= 0)\r
             {\r
-                if (isBufferNeededLater (ourRenderingIndex, AudioProcessorGraph::midiChannelIndex, src))\r
+                if (isBufferNeededLater (c, ourRenderingIndex, midiChannelIndex, src))\r
                 {\r
                     // can't mess up this channel because it's needed later by another node, so we\r
                     // need to use a copy of it..\r
@@ -655,18 +1153,22 @@ struct RenderSequenceBuilder
         int midiBufferToUse = -1;\r
         int reusableInputIndex = -1;\r
 \r
-        for (int i = 0; i < sources.size(); ++i)\r
         {\r
-            auto src = sources.getReference (i);\r
-            auto sourceBufIndex = getBufferContaining (src);\r
-\r
-            if (sourceBufIndex >= 0\r
-                 && ! isBufferNeededLater (ourRenderingIndex, AudioProcessorGraph::midiChannelIndex, src))\r
+            auto i = 0;\r
+            for (const auto& src : sources)\r
             {\r
-                // we've found one of our input buffers that can be re-used..\r
-                reusableInputIndex = i;\r
-                midiBufferToUse = sourceBufIndex;\r
-                break;\r
+                auto sourceBufIndex = getBufferContaining (src);\r
+\r
+                if (sourceBufIndex >= 0\r
+                    && ! isBufferNeededLater (c, ourRenderingIndex, midiChannelIndex, src))\r
+                {\r
+                    // we've found one of our input buffers that can be re-used..\r
+                    reusableInputIndex = i;\r
+                    midiBufferToUse = sourceBufIndex;\r
+                    break;\r
+                }\r
+\r
+                ++i;\r
             }\r
         }\r
 \r
@@ -676,7 +1178,7 @@ struct RenderSequenceBuilder
             midiBufferToUse = getFreeBuffer (midiBuffers);\r
             jassert (midiBufferToUse >= 0);\r
 \r
-            auto srcIndex = getBufferContaining (sources.getUnchecked(0));\r
+            auto srcIndex = getBufferContaining (*sources.begin());\r
 \r
             if (srcIndex >= 0)\r
                 sequence.addCopyMidiBufferOp (srcIndex, midiBufferToUse);\r
@@ -686,21 +1188,30 @@ struct RenderSequenceBuilder
             reusableInputIndex = 0;\r
         }\r
 \r
-        for (int i = 0; i < sources.size(); ++i)\r
         {\r
-            if (i != reusableInputIndex)\r
+            auto i = 0;\r
+            for (const auto& src : sources)\r
             {\r
-                auto srcIndex = getBufferContaining (sources.getUnchecked(i));\r
+                if (i != reusableInputIndex)\r
+                {\r
+                    auto srcIndex = getBufferContaining (src);\r
 \r
-                if (srcIndex >= 0)\r
-                    sequence.addAddMidiBufferOp (srcIndex, midiBufferToUse);\r
+                    if (srcIndex >= 0)\r
+                        sequence.addAddMidiBufferOp (srcIndex, midiBufferToUse);\r
+                }\r
+\r
+                ++i;\r
             }\r
         }\r
 \r
         return midiBufferToUse;\r
     }\r
 \r
-    void createRenderingOpsForNode (Node& node, const int ourRenderingIndex)\r
+    template <typename RenderSequence>\r
+    void createRenderingOpsForNode (const Connections& c,\r
+                                    RenderSequence& sequence,\r
+                                    Node& node,\r
+                                    const int ourRenderingIndex)\r
     {\r
         auto& processor = *node.getProcessor();\r
         auto numIns  = processor.getTotalNumInputChannels();\r
@@ -708,12 +1219,17 @@ struct RenderSequenceBuilder
         auto totalChans = jmax (numIns, numOuts);\r
 \r
         Array<int> audioChannelsToUse;\r
-        auto maxLatency = getInputLatencyForNode (node.nodeID);\r
+        auto maxLatency = getInputLatencyForNode (c, node.nodeID);\r
 \r
         for (int inputChan = 0; inputChan < numIns; ++inputChan)\r
         {\r
             // get a list of all the inputs to this node\r
-            auto index = findBufferForInputAudioChannel (node, inputChan, ourRenderingIndex, maxLatency);\r
+            auto index = findBufferForInputAudioChannel (c,\r
+                                                         sequence,\r
+                                                         node,\r
+                                                         inputChan,\r
+                                                         ourRenderingIndex,\r
+                                                         maxLatency);\r
             jassert (index >= 0);\r
 \r
             audioChannelsToUse.add (index);\r
@@ -731,10 +1247,10 @@ struct RenderSequenceBuilder
             audioBuffers.getReference (index).channel = { node.nodeID, outputChan };\r
         }\r
 \r
-        auto midiBufferToUse = findBufferForInputMidiChannel (node, ourRenderingIndex);\r
+        auto midiBufferToUse = findBufferForInputMidiChannel (c, sequence, node, ourRenderingIndex);\r
 \r
         if (processor.producesMidi())\r
-            midiBuffers.getReference (midiBufferToUse).channel = { node.nodeID, AudioProcessorGraph::midiChannelIndex };\r
+            midiBuffers.getReference (midiBufferToUse).channel = { node.nodeID, midiChannelIndex };\r
 \r
         delays.set (node.nodeID.uid, maxLatency + processor.getLatencySamples());\r
 \r
@@ -745,18 +1261,6 @@ struct RenderSequenceBuilder
     }\r
 \r
     //==============================================================================\r
-    Array<AudioProcessorGraph::NodeAndChannel> getSourcesForChannel (Node& node, int inputChannelIndex)\r
-    {\r
-        Array<AudioProcessorGraph::NodeAndChannel> results;\r
-        AudioProcessorGraph::NodeAndChannel nc { node.nodeID, inputChannelIndex };\r
-\r
-        for (auto&& c : graph.getConnections())\r
-            if (c.destination == nc)\r
-                results.add (c.source);\r
-\r
-        return results;\r
-    }\r
-\r
     static int getFreeBuffer (Array<AssignedBuffer>& buffers)\r
     {\r
         for (int i = 1; i < buffers.size(); ++i)\r
@@ -767,7 +1271,7 @@ struct RenderSequenceBuilder
         return buffers.size() - 1;\r
     }\r
 \r
-    int getBufferContaining (AudioProcessorGraph::NodeAndChannel output) const noexcept\r
+    int getBufferContaining (NodeAndChannel output) const noexcept\r
     {\r
         int i = 0;\r
 \r
@@ -782,16 +1286,19 @@ struct RenderSequenceBuilder
         return -1;\r
     }\r
 \r
-    void markAnyUnusedBuffersAsFree (Array<AssignedBuffer>& buffers, const int stepIndex)\r
+    void markAnyUnusedBuffersAsFree (const Connections& c,\r
+                                     Array<AssignedBuffer>& buffers,\r
+                                     const int stepIndex)\r
     {\r
         for (auto& b : buffers)\r
-            if (b.isAssigned() && ! isBufferNeededLater (stepIndex, -1, b.channel))\r
+            if (b.isAssigned() && ! isBufferNeededLater (c, stepIndex, -1, b.channel))\r
                 b.setFree();\r
     }\r
 \r
-    bool isBufferNeededLater (int stepIndexToSearchFrom,\r
+    bool isBufferNeededLater (const Connections& c,\r
+                              int stepIndexToSearchFrom,\r
                               int inputChannelOfIndexToIgnore,\r
-                              AudioProcessorGraph::NodeAndChannel output) const\r
+                              NodeAndChannel output) const\r
     {\r
         while (stepIndexToSearchFrom < orderedNodes.size())\r
         {\r
@@ -799,15 +1306,15 @@ struct RenderSequenceBuilder
 \r
             if (output.isMIDI())\r
             {\r
-                if (inputChannelOfIndexToIgnore != AudioProcessorGraph::midiChannelIndex\r
-                     && graph.isConnected ({ { output.nodeID, AudioProcessorGraph::midiChannelIndex },\r
-                                             { node->nodeID,  AudioProcessorGraph::midiChannelIndex } }))\r
+                if (inputChannelOfIndexToIgnore != midiChannelIndex\r
+                    && c.isConnected ({ { output.nodeID, midiChannelIndex },\r
+                                        { node->nodeID,  midiChannelIndex } }))\r
                     return true;\r
             }\r
             else\r
             {\r
                 for (int i = 0; i < node->getProcessor()->getTotalNumInputChannels(); ++i)\r
-                    if (i != inputChannelOfIndexToIgnore && graph.isConnected ({ output, { node->nodeID, i } }))\r
+                    if (i != inputChannelOfIndexToIgnore && c.isConnected ({ output, { node->nodeID, i } }))\r
                         return true;\r
             }\r
 \r
@@ -818,625 +1325,513 @@ struct RenderSequenceBuilder
         return false;\r
     }\r
 \r
-    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (RenderSequenceBuilder)\r
-};\r
-\r
-//==============================================================================\r
-AudioProcessorGraph::Connection::Connection (NodeAndChannel src, NodeAndChannel dst) noexcept\r
-    : source (src), destination (dst)\r
-{\r
-}\r
-\r
-bool AudioProcessorGraph::Connection::operator== (const Connection& other) const noexcept\r
-{\r
-    return source == other.source && destination == other.destination;\r
-}\r
-\r
-bool AudioProcessorGraph::Connection::operator!= (const Connection& c) const noexcept\r
-{\r
-    return ! operator== (c);\r
-}\r
-\r
-bool AudioProcessorGraph::Connection::operator< (const Connection& other) const noexcept\r
-{\r
-    if (source.nodeID != other.source.nodeID)\r
-        return source.nodeID < other.source.nodeID;\r
-\r
-    if (destination.nodeID != other.destination.nodeID)\r
-        return destination.nodeID < other.destination.nodeID;\r
-\r
-    if (source.channelIndex != other.source.channelIndex)\r
-        return source.channelIndex < other.source.channelIndex;\r
-\r
-    return destination.channelIndex < other.destination.channelIndex;\r
-}\r
-\r
-//==============================================================================\r
-AudioProcessorGraph::Node::Node (NodeID n, std::unique_ptr<AudioProcessor> p) noexcept\r
-    : nodeID (n), processor (std::move (p))\r
-{\r
-    jassert (processor != nullptr);\r
-}\r
-\r
-void AudioProcessorGraph::Node::prepare (double newSampleRate, int newBlockSize,\r
-                                         AudioProcessorGraph* graph, ProcessingPrecision precision)\r
-{\r
-    const ScopedLock lock (processorLock);\r
-\r
-    if (! isPrepared)\r
+    template <typename RenderSequence>\r
+    RenderSequenceBuilder (const Nodes& n, const Connections& c, RenderSequence& sequence)\r
+        : orderedNodes (createOrderedNodeList (n, c))\r
     {\r
-        setParentGraph (graph);\r
-\r
-        // try to align the precision of the processor and the graph\r
-        processor->setProcessingPrecision (processor->supportsDoublePrecisionProcessing() ? precision\r
-                                                                                          : singlePrecision);\r
-\r
-        processor->setRateAndBufferSizeDetails (newSampleRate, newBlockSize);\r
-        processor->prepareToPlay (newSampleRate, newBlockSize);\r
-\r
-        // This may be checked from other threads that haven't taken the processorLock,\r
-        // so we need to leave it until the processor has been completely prepared\r
-        isPrepared = true;\r
-    }\r
-}\r
+        audioBuffers.add (AssignedBuffer::createReadOnlyEmpty()); // first buffer is read-only zeros\r
+        midiBuffers .add (AssignedBuffer::createReadOnlyEmpty());\r
 \r
-void AudioProcessorGraph::Node::unprepare()\r
-{\r
-    const ScopedLock lock (processorLock);\r
+        for (int i = 0; i < orderedNodes.size(); ++i)\r
+        {\r
+            createRenderingOpsForNode (c, sequence, *orderedNodes.getUnchecked (i), i);\r
+            markAnyUnusedBuffersAsFree (c, audioBuffers, i);\r
+            markAnyUnusedBuffersAsFree (c, midiBuffers, i);\r
+        }\r
 \r
-    if (isPrepared)\r
-    {\r
-        isPrepared = false;\r
-        processor->releaseResources();\r
+        sequence.numBuffersNeeded = audioBuffers.size();\r
+        sequence.numMidiBuffersNeeded = midiBuffers.size();\r
     }\r
-}\r
-\r
-void AudioProcessorGraph::Node::setParentGraph (AudioProcessorGraph* const graph) const\r
-{\r
-    const ScopedLock lock (processorLock);\r
+};\r
 \r
-    if (auto* ioProc = dynamic_cast<AudioProcessorGraph::AudioGraphIOProcessor*> (processor.get()))\r
-        ioProc->setParentGraph (graph);\r
-}\r
+//==============================================================================\r
+/*  A full graph of audio processors, ready to process at a particular sample rate, block size,\r
+    and precision.\r
 \r
-bool AudioProcessorGraph::Node::Connection::operator== (const Connection& other) const noexcept\r
+    Instances of this class will be created on the main thread, and then passed over to the audio\r
+    thread for processing.\r
+*/\r
+class RenderSequence\r
 {\r
-    return otherNode == other.otherNode\r
-        && thisChannel == other.thisChannel\r
-        && otherChannel == other.otherChannel;\r
-}\r
+public:\r
+    using AudioGraphIOProcessor = AudioProcessorGraph::AudioGraphIOProcessor;\r
 \r
-//==============================================================================\r
-bool AudioProcessorGraph::Node::isBypassed() const noexcept\r
-{\r
-    if (processor != nullptr)\r
+    RenderSequence (PrepareSettings s, const Nodes& n, const Connections& c)\r
+        : RenderSequence (s,\r
+                          RenderSequenceBuilder::build<GraphRenderSequence<float>>  (n, c),\r
+                          RenderSequenceBuilder::build<GraphRenderSequence<double>> (n, c))\r
     {\r
-        if (auto* bypassParam = processor->getBypassParameter())\r
-            return (bypassParam->getValue() != 0.0f);\r
     }\r
 \r
-    return bypassed;\r
-}\r
-\r
-void AudioProcessorGraph::Node::setBypassed (bool shouldBeBypassed) noexcept\r
-{\r
-    if (processor != nullptr)\r
+    void process (AudioBuffer<float>& audio, MidiBuffer& midi, AudioPlayHead* playHead)\r
     {\r
-        if (auto* bypassParam = processor->getBypassParameter())\r
-            bypassParam->setValueNotifyingHost (shouldBeBypassed ? 1.0f : 0.0f);\r
+        renderSequenceF.perform (audio, midi, playHead);\r
     }\r
 \r
-    bypassed = shouldBeBypassed;\r
-}\r
-\r
-//==============================================================================\r
-struct AudioProcessorGraph::RenderSequenceFloat   : public GraphRenderSequence<float> {};\r
-struct AudioProcessorGraph::RenderSequenceDouble  : public GraphRenderSequence<double> {};\r
-\r
-//==============================================================================\r
-AudioProcessorGraph::AudioProcessorGraph()\r
-{\r
-}\r
-\r
-AudioProcessorGraph::~AudioProcessorGraph()\r
-{\r
-    cancelPendingUpdate();\r
-    clearRenderingSequence();\r
-    clear();\r
-}\r
-\r
-const String AudioProcessorGraph::getName() const\r
-{\r
-    return "Audio Graph";\r
-}\r
-\r
-//==============================================================================\r
-void AudioProcessorGraph::topologyChanged()\r
-{\r
-    sendChangeMessage();\r
-\r
-    if (isPrepared)\r
-        updateOnMessageThread (*this);\r
-}\r
-\r
-void AudioProcessorGraph::clear()\r
-{\r
-    const ScopedLock sl (getCallbackLock());\r
-\r
-    if (nodes.isEmpty())\r
-        return;\r
-\r
-    nodes.clear();\r
-    topologyChanged();\r
-}\r
-\r
-AudioProcessorGraph::Node* AudioProcessorGraph::getNodeForId (NodeID nodeID) const\r
-{\r
-    for (auto* n : nodes)\r
-        if (n->nodeID == nodeID)\r
-            return n;\r
-\r
-    return {};\r
-}\r
-\r
-AudioProcessorGraph::Node::Ptr AudioProcessorGraph::addNode (std::unique_ptr<AudioProcessor> newProcessor, NodeID nodeID)\r
-{\r
-    if (newProcessor == nullptr || newProcessor.get() == this)\r
+    void process (AudioBuffer<double>& audio, MidiBuffer& midi, AudioPlayHead* playHead)\r
     {\r
-        jassertfalse;\r
-        return {};\r
+        renderSequenceD.perform (audio, midi, playHead);\r
     }\r
 \r
-    if (nodeID == NodeID())\r
-        nodeID.uid = ++(lastNodeID.uid);\r
-\r
-    for (auto* n : nodes)\r
+    void processIO (AudioGraphIOProcessor& io, AudioBuffer<float>& audio, MidiBuffer& midi)\r
     {\r
-        if (n->getProcessor() == newProcessor.get() || n->nodeID == nodeID)\r
-        {\r
-            jassertfalse; // Cannot add two copies of the same processor, or duplicate node IDs!\r
-            return {};\r
-        }\r
+        processIOBlock (io, renderSequenceF, audio, midi);\r
     }\r
 \r
-    if (lastNodeID < nodeID)\r
-        lastNodeID = nodeID;\r
-\r
-    newProcessor->setPlayHead (getPlayHead());\r
-\r
-    Node::Ptr n (new Node (nodeID, std::move (newProcessor)));\r
-\r
+    void processIO (AudioGraphIOProcessor& io, AudioBuffer<double>& audio, MidiBuffer& midi)\r
     {\r
-        const ScopedLock sl (getCallbackLock());\r
-        nodes.add (n.get());\r
+        processIOBlock (io, renderSequenceD, audio, midi);\r
     }\r
 \r
-    n->setParentGraph (this);\r
-    topologyChanged();\r
-    return n;\r
-}\r
-\r
-AudioProcessorGraph::Node::Ptr AudioProcessorGraph::removeNode (NodeID nodeId)\r
-{\r
-    const ScopedLock sl (getCallbackLock());\r
+    int getLatencySamples() const { return latencySamples; }\r
+    PrepareSettings getSettings() const { return settings; }\r
 \r
-    for (int i = nodes.size(); --i >= 0;)\r
+private:\r
+    template <typename FloatType, typename SequenceType>\r
+    static void processIOBlock (AudioGraphIOProcessor& io,\r
+                                SequenceType& sequence,\r
+                                AudioBuffer<FloatType>& buffer,\r
+                                MidiBuffer& midiMessages)\r
     {\r
-        if (nodes.getUnchecked (i)->nodeID == nodeId)\r
+        switch (io.getType())\r
         {\r
-            disconnectNode (nodeId);\r
-            auto node = nodes.removeAndReturn (i);\r
-            topologyChanged();\r
-            return node;\r
-        }\r
-    }\r
-\r
-    return {};\r
-}\r
-\r
-AudioProcessorGraph::Node::Ptr AudioProcessorGraph::removeNode (Node* node)\r
-{\r
-    if (node != nullptr)\r
-        return removeNode (node->nodeID);\r
-\r
-    jassertfalse;\r
-    return {};\r
-}\r
-\r
-//==============================================================================\r
-void AudioProcessorGraph::getNodeConnections (Node& node, std::vector<Connection>& connections)\r
-{\r
-    for (auto& i : node.inputs)\r
-        connections.push_back ({ { i.otherNode->nodeID, i.otherChannel }, { node.nodeID, i.thisChannel } });\r
-\r
-    for (auto& o : node.outputs)\r
-        connections.push_back ({ { node.nodeID, o.thisChannel }, { o.otherNode->nodeID, o.otherChannel } });\r
-}\r
-\r
-std::vector<AudioProcessorGraph::Connection> AudioProcessorGraph::getConnections() const\r
-{\r
-    std::vector<Connection> connections;\r
-\r
-    for (auto& n : nodes)\r
-        getNodeConnections (*n, connections);\r
-\r
-    std::sort (connections.begin(), connections.end());\r
-    auto last = std::unique (connections.begin(), connections.end());\r
-    connections.erase (last, connections.end());\r
-\r
-    return connections;\r
-}\r
-\r
-bool AudioProcessorGraph::isConnected (Node* source, int sourceChannel, Node* dest, int destChannel) const noexcept\r
-{\r
-    for (auto& o : source->outputs)\r
-        if (o.otherNode == dest && o.thisChannel == sourceChannel && o.otherChannel == destChannel)\r
-            return true;\r
-\r
-    return false;\r
-}\r
-\r
-bool AudioProcessorGraph::isConnected (const Connection& c) const noexcept\r
-{\r
-    if (auto* source = getNodeForId (c.source.nodeID))\r
-        if (auto* dest = getNodeForId (c.destination.nodeID))\r
-            return isConnected (source, c.source.channelIndex,\r
-                                dest, c.destination.channelIndex);\r
-\r
-    return false;\r
-}\r
-\r
-bool AudioProcessorGraph::isConnected (NodeID srcID, NodeID destID) const noexcept\r
-{\r
-    if (auto* source = getNodeForId (srcID))\r
-        if (auto* dest = getNodeForId (destID))\r
-            for (auto& out : source->outputs)\r
-                if (out.otherNode == dest)\r
-                    return true;\r
-\r
-    return false;\r
-}\r
+            case AudioGraphIOProcessor::audioOutputNode:\r
+            {\r
+                auto&& currentAudioOutputBuffer = sequence.currentAudioOutputBuffer;\r
 \r
-bool AudioProcessorGraph::isAnInputTo (Node& src, Node& dst) const noexcept\r
-{\r
-    jassert (nodes.contains (&src));\r
-    jassert (nodes.contains (&dst));\r
+                for (int i = jmin (currentAudioOutputBuffer.getNumChannels(), buffer.getNumChannels()); --i >= 0;)\r
+                    currentAudioOutputBuffer.addFrom (i, 0, buffer, i, 0, buffer.getNumSamples());\r
 \r
-    return isAnInputTo (src, dst, nodes.size());\r
-}\r
+                break;\r
+            }\r
 \r
-bool AudioProcessorGraph::isAnInputTo (Node& src, Node& dst, int recursionCheck) const noexcept\r
-{\r
-    for (auto&& i : dst.inputs)\r
-        if (i.otherNode == &src)\r
-            return true;\r
+            case AudioGraphIOProcessor::audioInputNode:\r
+            {\r
+                auto* currentInputBuffer = sequence.currentAudioInputBuffer;\r
 \r
-    if (recursionCheck > 0)\r
-        for (auto&& i : dst.inputs)\r
-            if (isAnInputTo (src, *i.otherNode, recursionCheck - 1))\r
-                return true;\r
+                for (int i = jmin (currentInputBuffer->getNumChannels(), buffer.getNumChannels()); --i >= 0;)\r
+                    buffer.copyFrom (i, 0, *currentInputBuffer, i, 0, buffer.getNumSamples());\r
 \r
-    return false;\r
-}\r
+                break;\r
+            }\r
 \r
-bool AudioProcessorGraph::canConnect (Node* source, int sourceChannel, Node* dest, int destChannel) const noexcept\r
-{\r
-    bool sourceIsMIDI = sourceChannel == midiChannelIndex;\r
-    bool destIsMIDI   = destChannel == midiChannelIndex;\r
+            case AudioGraphIOProcessor::midiOutputNode:\r
+                sequence.currentMidiOutputBuffer.addEvents (midiMessages, 0, buffer.getNumSamples(), 0);\r
+                break;\r
 \r
-    if (sourceChannel < 0\r
-         || destChannel < 0\r
-         || source == dest\r
-         || sourceIsMIDI != destIsMIDI)\r
-        return false;\r
+            case AudioGraphIOProcessor::midiInputNode:\r
+                midiMessages.addEvents (*sequence.currentMidiInputBuffer, 0, buffer.getNumSamples(), 0);\r
+                break;\r
 \r
-    if (source == nullptr\r
-         || (! sourceIsMIDI && sourceChannel >= source->processor->getTotalNumOutputChannels())\r
-         || (sourceIsMIDI && ! source->processor->producesMidi()))\r
-        return false;\r
+            default:\r
+                break;\r
+        }\r
+    }\r
 \r
-    if (dest == nullptr\r
-         || (! destIsMIDI && destChannel >= dest->processor->getTotalNumInputChannels())\r
-         || (destIsMIDI && ! dest->processor->acceptsMidi()))\r
-        return false;\r
+    template <typename Float, typename Double>\r
+    RenderSequence (PrepareSettings s, Float f, Double d)\r
+        : settings (s),\r
+          renderSequenceF (std::move (f.sequence)),\r
+          renderSequenceD (std::move (d.sequence)),\r
+          latencySamples (f.latencySamples)\r
+    {\r
+        jassert (f.latencySamples == d.latencySamples);\r
 \r
-    return ! isConnected (source, sourceChannel, dest, destChannel);\r
-}\r
+        renderSequenceF.prepareBuffers (settings.blockSize);\r
+        renderSequenceD.prepareBuffers (settings.blockSize);\r
+    }\r
 \r
-bool AudioProcessorGraph::canConnect (const Connection& c) const\r
-{\r
-    if (auto* source = getNodeForId (c.source.nodeID))\r
-        if (auto* dest = getNodeForId (c.destination.nodeID))\r
-            return canConnect (source, c.source.channelIndex,\r
-                               dest, c.destination.channelIndex);\r
+    PrepareSettings settings;\r
+    GraphRenderSequence<float>  renderSequenceF;\r
+    GraphRenderSequence<double> renderSequenceD;\r
+    int latencySamples = 0;\r
+};\r
 \r
-    return false;\r
-}\r
+//==============================================================================\r
+/*  Facilitates wait-free render-sequence updates.\r
 \r
-bool AudioProcessorGraph::addConnection (const Connection& c)\r
+    Topology updates always happen on the main thread (or synchronised with the main thread).\r
+    After updating the graph, the 'baked' graph is passed to RenderSequenceExchange::set.\r
+    At the top of the audio callback, RenderSequenceExchange::updateAudioThreadState will\r
+    attempt to install the most-recently-baked graph, if there's one waiting.\r
+*/\r
+class RenderSequenceExchange : private Timer\r
 {\r
-    if (auto* source = getNodeForId (c.source.nodeID))\r
+public:\r
+    RenderSequenceExchange()\r
     {\r
-        if (auto* dest = getNodeForId (c.destination.nodeID))\r
-        {\r
-            auto sourceChan = c.source.channelIndex;\r
-            auto destChan = c.destination.channelIndex;\r
+        startTimer (500);\r
+    }\r
 \r
-            if (canConnect (source, sourceChan, dest, destChan))\r
-            {\r
-                source->outputs.add ({ dest, destChan, sourceChan });\r
-                dest->inputs.add ({ source, sourceChan, destChan });\r
-                jassert (isConnected (c));\r
-                topologyChanged();\r
-                return true;\r
-            }\r
-        }\r
+    ~RenderSequenceExchange() override\r
+    {\r
+        stopTimer();\r
     }\r
 \r
-    return false;\r
-}\r
+    void set (std::unique_ptr<RenderSequence>&& next)\r
+    {\r
+        const SpinLock::ScopedLockType lock (mutex);\r
+        mainThreadState = std::move (next);\r
+        isNew = true;\r
+    }\r
 \r
-bool AudioProcessorGraph::removeConnection (const Connection& c)\r
-{\r
-    if (auto* source = getNodeForId (c.source.nodeID))\r
+    /** Call from the audio thread only. */\r
+    void updateAudioThreadState()\r
     {\r
-        if (auto* dest = getNodeForId (c.destination.nodeID))\r
-        {\r
-            auto sourceChan = c.source.channelIndex;\r
-            auto destChan = c.destination.channelIndex;\r
+        const SpinLock::ScopedTryLockType lock (mutex);\r
 \r
-            if (isConnected (source, sourceChan, dest, destChan))\r
-            {\r
-                source->outputs.removeAllInstancesOf ({ dest, destChan, sourceChan });\r
-                dest->inputs.removeAllInstancesOf ({ source, sourceChan, destChan });\r
-                topologyChanged();\r
-                return true;\r
-            }\r
+        if (lock.isLocked() && isNew)\r
+        {\r
+            // Swap pointers rather than assigning to avoid calling delete here\r
+            std::swap (mainThreadState, audioThreadState);\r
+            isNew = false;\r
         }\r
     }\r
 \r
-    return false;\r
-}\r
+    /** Call from the audio thread only. */\r
+    RenderSequence* getAudioThreadState() const { return audioThreadState.get(); }\r
 \r
-bool AudioProcessorGraph::disconnectNode (NodeID nodeID)\r
-{\r
-    if (auto* node = getNodeForId (nodeID))\r
+private:\r
+    void timerCallback() override\r
     {\r
-        std::vector<Connection> connections;\r
-        getNodeConnections (*node, connections);\r
-\r
-        if (! connections.empty())\r
-        {\r
-            for (auto c : connections)\r
-                removeConnection (c);\r
+        const SpinLock::ScopedLockType lock (mutex);\r
 \r
-            return true;\r
-        }\r
+        if (! isNew)\r
+            mainThreadState.reset();\r
     }\r
 \r
-    return false;\r
+    SpinLock mutex;\r
+    std::unique_ptr<RenderSequence> mainThreadState, audioThreadState;\r
+    bool isNew = false;\r
+};\r
+\r
+//==============================================================================\r
+AudioProcessorGraph::Connection::Connection (NodeAndChannel src, NodeAndChannel dst) noexcept\r
+    : source (src), destination (dst)\r
+{\r
 }\r
 \r
-bool AudioProcessorGraph::isLegal (Node* source, int sourceChannel, Node* dest, int destChannel) const noexcept\r
+bool AudioProcessorGraph::Connection::operator== (const Connection& other) const noexcept\r
 {\r
-    return (sourceChannel == midiChannelIndex ? source->processor->producesMidi()\r
-                                              : isPositiveAndBelow (sourceChannel, source->processor->getTotalNumOutputChannels()))\r
-        && (destChannel == midiChannelIndex ? dest->processor->acceptsMidi()\r
-                                            : isPositiveAndBelow (destChannel, dest->processor->getTotalNumInputChannels()));\r
+    return source == other.source && destination == other.destination;\r
 }\r
 \r
-bool AudioProcessorGraph::isConnectionLegal (const Connection& c) const\r
+bool AudioProcessorGraph::Connection::operator!= (const Connection& c) const noexcept\r
 {\r
-    if (auto* source = getNodeForId (c.source.nodeID))\r
-        if (auto* dest = getNodeForId (c.destination.nodeID))\r
-            return isLegal (source, c.source.channelIndex, dest, c.destination.channelIndex);\r
+    return ! operator== (c);\r
+}\r
 \r
-    return false;\r
+bool AudioProcessorGraph::Connection::operator< (const Connection& other) const noexcept\r
+{\r
+    const auto tie = [] (auto& x)\r
+    {\r
+        return std::tie (x.source.nodeID,\r
+                         x.destination.nodeID,\r
+                         x.source.channelIndex,\r
+                         x.destination.channelIndex);\r
+    };\r
+    return tie (*this) < tie (other);\r
 }\r
 \r
-bool AudioProcessorGraph::removeIllegalConnections()\r
+//==============================================================================\r
+class AudioProcessorGraph::Pimpl : public AsyncUpdater\r
 {\r
-    bool anyRemoved = false;\r
+public:\r
+    explicit Pimpl (AudioProcessorGraph& o) : owner (&o) {}\r
 \r
-    for (auto* node : nodes)\r
+    ~Pimpl() override\r
     {\r
-        std::vector<Connection> connections;\r
-        getNodeConnections (*node, connections);\r
-\r
-        for (auto c : connections)\r
-            if (! isConnectionLegal (c))\r
-                anyRemoved = removeConnection (c) || anyRemoved;\r
+        cancelPendingUpdate();\r
+        clear (UpdateKind::sync);\r
     }\r
 \r
-    return anyRemoved;\r
-}\r
+    const auto& getNodes() const { return nodes.getNodes(); }\r
 \r
-//==============================================================================\r
-void AudioProcessorGraph::clearRenderingSequence()\r
-{\r
-    std::unique_ptr<RenderSequenceFloat> oldSequenceF;\r
-    std::unique_ptr<RenderSequenceDouble> oldSequenceD;\r
+    void clear (UpdateKind updateKind)\r
+    {\r
+        if (getNodes().isEmpty())\r
+            return;\r
+\r
+        nodes = Nodes{};\r
+        connections = Connections{};\r
+        topologyChanged (updateKind);\r
+    }\r
 \r
+    auto getNodeForId (NodeID nodeID) const\r
     {\r
-        const ScopedLock sl (getCallbackLock());\r
-        std::swap (renderSequenceFloat, oldSequenceF);\r
-        std::swap (renderSequenceDouble, oldSequenceD);\r
+        return nodes.getNodeForId (nodeID);\r
     }\r
-}\r
 \r
-bool AudioProcessorGraph::anyNodesNeedPreparing() const noexcept\r
-{\r
-    for (auto* node : nodes)\r
-        if (! node->isPrepared)\r
-            return true;\r
+    Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor,\r
+                       const NodeID nodeID,\r
+                       UpdateKind updateKind)\r
+    {\r
+        if (newProcessor.get() == owner)\r
+        {\r
+            jassertfalse;\r
+            return nullptr;\r
+        }\r
 \r
-    return false;\r
-}\r
+        const auto idToUse = nodeID == NodeID() ? NodeID { ++(lastNodeID.uid) } : nodeID;\r
 \r
-void AudioProcessorGraph::buildRenderingSequence()\r
-{\r
-    auto newSequenceF = std::make_unique<RenderSequenceFloat>();\r
-    auto newSequenceD = std::make_unique<RenderSequenceDouble>();\r
+        auto added = nodes.addNode (std::move (newProcessor), idToUse);\r
+\r
+        if (added == nullptr)\r
+            return nullptr;\r
 \r
-    RenderSequenceBuilder<RenderSequenceFloat>  builderF (*this, *newSequenceF);\r
-    RenderSequenceBuilder<RenderSequenceDouble> builderD (*this, *newSequenceD);\r
+        if (lastNodeID < idToUse)\r
+            lastNodeID = idToUse;\r
 \r
-    const ScopedLock sl (getCallbackLock());\r
+        setParentGraph (added->getProcessor());\r
 \r
-    const auto currentBlockSize = getBlockSize();\r
-    newSequenceF->prepareBuffers (currentBlockSize);\r
-    newSequenceD->prepareBuffers (currentBlockSize);\r
+        topologyChanged (updateKind);\r
+        return added;\r
+    }\r
 \r
-    if (anyNodesNeedPreparing())\r
+    Node::Ptr removeNode (NodeID nodeID, UpdateKind updateKind)\r
     {\r
-        renderSequenceFloat.reset();\r
-        renderSequenceDouble.reset();\r
+        connections.disconnectNode (nodeID);\r
+        auto result = nodes.removeNode (nodeID);\r
+        topologyChanged (updateKind);\r
+        return result;\r
+    }\r
 \r
-        for (auto* node : nodes)\r
-            node->prepare (getSampleRate(), currentBlockSize, this, getProcessingPrecision());\r
+    std::vector<Connection> getConnections() const\r
+    {\r
+        return connections.getConnections();\r
     }\r
 \r
-    isPrepared = 1;\r
+    bool isConnected (const Connection& c) const\r
+    {\r
+        return connections.isConnected (c);\r
+    }\r
 \r
-    std::swap (renderSequenceFloat,  newSequenceF);\r
-    std::swap (renderSequenceDouble, newSequenceD);\r
-}\r
+    bool isConnected (NodeID srcID, NodeID destID) const\r
+    {\r
+        return connections.isConnected (srcID, destID);\r
+    }\r
 \r
-void AudioProcessorGraph::handleAsyncUpdate()\r
-{\r
-    buildRenderingSequence();\r
-}\r
+    bool isAnInputTo (const Node& src, const Node& dst) const\r
+    {\r
+        return isAnInputTo (src.nodeID, dst.nodeID);\r
+    }\r
 \r
-//==============================================================================\r
-void AudioProcessorGraph::prepareToPlay (double sampleRate, int estimatedSamplesPerBlock)\r
-{\r
+    bool isAnInputTo (NodeID src, NodeID dst) const\r
     {\r
-        const ScopedLock sl (getCallbackLock());\r
-        setRateAndBufferSizeDetails (sampleRate, estimatedSamplesPerBlock);\r
+        return connections.isAnInputTo (src, dst);\r
+    }\r
 \r
-        const auto newPrepareSettings = [&]\r
-        {\r
-            PrepareSettings settings;\r
-            settings.precision  = getProcessingPrecision();\r
-            settings.sampleRate = sampleRate;\r
-            settings.blockSize  = estimatedSamplesPerBlock;\r
-            settings.valid      = true;\r
-            return settings;\r
-        }();\r
+    bool canConnect (const Connection& c) const\r
+    {\r
+        return connections.canConnect (nodes, c);\r
+    }\r
 \r
-        if (prepareSettings != newPrepareSettings)\r
-        {\r
-            unprepare();\r
-            prepareSettings = newPrepareSettings;\r
-        }\r
+    bool addConnection (const Connection& c, UpdateKind updateKind)\r
+    {\r
+        if (! connections.addConnection (nodes, c))\r
+            return false;\r
+\r
+        jassert (isConnected (c));\r
+        topologyChanged (updateKind);\r
+        return true;\r
     }\r
 \r
-    clearRenderingSequence();\r
+    bool removeConnection (const Connection& c, UpdateKind updateKind)\r
+    {\r
+        if (! connections.removeConnection (c))\r
+            return false;\r
 \r
-    updateOnMessageThread (*this);\r
-}\r
+        topologyChanged (updateKind);\r
+        return true;\r
+    }\r
 \r
-bool AudioProcessorGraph::supportsDoublePrecisionProcessing() const\r
-{\r
-    return true;\r
-}\r
+    bool disconnectNode (NodeID nodeID, UpdateKind updateKind)\r
+    {\r
+        if (! connections.disconnectNode (nodeID))\r
+            return false;\r
 \r
-void AudioProcessorGraph::unprepare()\r
-{\r
-    prepareSettings.valid = false;\r
+        topologyChanged (updateKind);\r
+        return true;\r
+    }\r
 \r
-    isPrepared = 0;\r
+    bool isConnectionLegal (const Connection& c) const\r
+    {\r
+        return connections.isConnectionLegal (nodes, c);\r
+    }\r
 \r
-    for (auto* n : nodes)\r
-        n->unprepare();\r
-}\r
+    bool removeIllegalConnections (UpdateKind updateKind)\r
+    {\r
+        const auto result = connections.removeIllegalConnections (nodes);\r
+        topologyChanged (updateKind);\r
+        return result;\r
+    }\r
 \r
-void AudioProcessorGraph::releaseResources()\r
-{\r
-    const ScopedLock sl (getCallbackLock());\r
+    //==============================================================================\r
+    void prepareToPlay (double sampleRate, int estimatedSamplesPerBlock)\r
+    {\r
+        owner->setRateAndBufferSizeDetails (sampleRate, estimatedSamplesPerBlock);\r
 \r
-    cancelPendingUpdate();\r
+        PrepareSettings settings;\r
+        settings.precision  = owner->getProcessingPrecision();\r
+        settings.sampleRate = sampleRate;\r
+        settings.blockSize  = estimatedSamplesPerBlock;\r
 \r
-    unprepare();\r
+        nodeStates.setState (settings);\r
 \r
-    if (renderSequenceFloat != nullptr)\r
-        renderSequenceFloat->releaseBuffers();\r
+        topologyChanged (UpdateKind::sync);\r
+    }\r
 \r
-    if (renderSequenceDouble != nullptr)\r
-        renderSequenceDouble->releaseBuffers();\r
-}\r
+    void releaseResources()\r
+    {\r
+        nodeStates.setState (nullopt);\r
+        topologyChanged (UpdateKind::sync);\r
+    }\r
 \r
-void AudioProcessorGraph::reset()\r
-{\r
-    const ScopedLock sl (getCallbackLock());\r
+    void reset()\r
+    {\r
+        for (auto* n : getNodes())\r
+            n->getProcessor()->reset();\r
+    }\r
 \r
-    for (auto* n : nodes)\r
-        n->getProcessor()->reset();\r
-}\r
+    void setNonRealtime (bool isProcessingNonRealtime)\r
+    {\r
+        for (auto* n : getNodes())\r
+            n->getProcessor()->setNonRealtime (isProcessingNonRealtime);\r
+    }\r
 \r
-void AudioProcessorGraph::setNonRealtime (bool isProcessingNonRealtime) noexcept\r
-{\r
-    const ScopedLock sl (getCallbackLock());\r
+    template <typename Value>\r
+    void processBlock (AudioBuffer<Value>& audio, MidiBuffer& midi, AudioPlayHead* playHead)\r
+    {\r
+        renderSequenceExchange.updateAudioThreadState();\r
 \r
-    AudioProcessor::setNonRealtime (isProcessingNonRealtime);\r
+        if (renderSequenceExchange.getAudioThreadState() == nullptr && MessageManager::getInstance()->isThisTheMessageThread())\r
+            handleAsyncUpdate();\r
 \r
-    for (auto* n : nodes)\r
-        n->getProcessor()->setNonRealtime (isProcessingNonRealtime);\r
-}\r
+        if (owner->isNonRealtime())\r
+        {\r
+            while (renderSequenceExchange.getAudioThreadState() == nullptr)\r
+            {\r
+                Thread::sleep (1);\r
+                renderSequenceExchange.updateAudioThreadState();\r
+            }\r
+        }\r
 \r
-double AudioProcessorGraph::getTailLengthSeconds() const            { return 0; }\r
-bool AudioProcessorGraph::acceptsMidi() const                       { return true; }\r
-bool AudioProcessorGraph::producesMidi() const                      { return true; }\r
-void AudioProcessorGraph::getStateInformation (MemoryBlock&)        {}\r
-void AudioProcessorGraph::setStateInformation (const void*, int)    {}\r
+        auto* state = renderSequenceExchange.getAudioThreadState();\r
 \r
-template <typename FloatType, typename SequenceType>\r
-static void processBlockForBuffer (AudioBuffer<FloatType>& buffer, MidiBuffer& midiMessages,\r
-                                   AudioProcessorGraph& graph,\r
-                                   std::unique_ptr<SequenceType>& renderSequence,\r
-                                   std::atomic<bool>& isPrepared)\r
-{\r
-    if (graph.isNonRealtime())\r
-    {\r
-        while (! isPrepared)\r
-            Thread::sleep (1);\r
+        // Only process if the graph has the correct blockSize, sampleRate etc.\r
+        if (state != nullptr && state->getSettings() == nodeStates.getLastRequestedSettings())\r
+        {\r
+            state->process (audio, midi, playHead);\r
+        }\r
+        else\r
+        {\r
+            audio.clear();\r
+            midi.clear();\r
+        }\r
+    }\r
 \r
-        const ScopedLock sl (graph.getCallbackLock());\r
+    /*  Call from the audio thread only. */\r
+    auto* getAudioThreadState() const { return renderSequenceExchange.getAudioThreadState(); }\r
 \r
-        if (renderSequence != nullptr)\r
-            renderSequence->perform (buffer, midiMessages, graph.getPlayHead());\r
+private:\r
+    void setParentGraph (AudioProcessor* p) const\r
+    {\r
+        if (auto* ioProc = dynamic_cast<AudioGraphIOProcessor*> (p))\r
+            ioProc->setParentGraph (owner);\r
     }\r
-    else\r
+\r
+    void topologyChanged (UpdateKind updateKind)\r
     {\r
-        const ScopedLock sl (graph.getCallbackLock());\r
+        owner->sendChangeMessage();\r
+\r
+        if (updateKind == UpdateKind::sync && MessageManager::getInstance()->isThisTheMessageThread())\r
+            handleAsyncUpdate();\r
+        else\r
+            triggerAsyncUpdate();\r
+    }\r
 \r
-        if (isPrepared)\r
+    void handleAsyncUpdate() override\r
+    {\r
+        if (const auto newSettings = nodeStates.applySettings (nodes))\r
         {\r
-            if (renderSequence != nullptr)\r
-                renderSequence->perform (buffer, midiMessages, graph.getPlayHead());\r
+            for (const auto node : nodes.getNodes())\r
+                setParentGraph (node->getProcessor());\r
+\r
+            auto sequence = std::make_unique<RenderSequence> (*newSettings, nodes, connections);\r
+            owner->setLatencySamples (sequence->getLatencySamples());\r
+            renderSequenceExchange.set (std::move (sequence));\r
         }\r
         else\r
         {\r
-            buffer.clear();\r
-            midiMessages.clear();\r
+            renderSequenceExchange.set (nullptr);\r
         }\r
     }\r
+\r
+    AudioProcessorGraph* owner = nullptr;\r
+    Nodes nodes;\r
+    Connections connections;\r
+    NodeStates nodeStates;\r
+    RenderSequenceExchange renderSequenceExchange;\r
+    NodeID lastNodeID;\r
+};\r
+\r
+//==============================================================================\r
+AudioProcessorGraph::AudioProcessorGraph() : pimpl (std::make_unique<Pimpl> (*this)) {}\r
+AudioProcessorGraph::~AudioProcessorGraph() = default;\r
+\r
+const String AudioProcessorGraph::getName() const                   { return "Audio Graph"; }\r
+bool AudioProcessorGraph::supportsDoublePrecisionProcessing() const { return true; }\r
+double AudioProcessorGraph::getTailLengthSeconds() const            { return 0; }\r
+bool AudioProcessorGraph::acceptsMidi() const                       { return true; }\r
+bool AudioProcessorGraph::producesMidi() const                      { return true; }\r
+void AudioProcessorGraph::getStateInformation (MemoryBlock&)        {}\r
+void AudioProcessorGraph::setStateInformation (const void*, int)    {}\r
+\r
+void AudioProcessorGraph::processBlock (AudioBuffer<float>&  audio, MidiBuffer& midi)                       { return pimpl->processBlock (audio, midi, getPlayHead()); }\r
+void AudioProcessorGraph::processBlock (AudioBuffer<double>& audio, MidiBuffer& midi)                       { return pimpl->processBlock (audio, midi, getPlayHead()); }\r
+std::vector<AudioProcessorGraph::Connection> AudioProcessorGraph::getConnections() const                    { return pimpl->getConnections(); }\r
+bool AudioProcessorGraph::addConnection (const Connection& c, UpdateKind updateKind)                        { return pimpl->addConnection (c, updateKind); }\r
+bool AudioProcessorGraph::removeConnection (const Connection& c, UpdateKind updateKind)                     { return pimpl->removeConnection (c, updateKind); }\r
+void AudioProcessorGraph::prepareToPlay (double sampleRate, int estimatedSamplesPerBlock)                   { return pimpl->prepareToPlay (sampleRate, estimatedSamplesPerBlock); }\r
+void AudioProcessorGraph::clear (UpdateKind updateKind)                                                     { return pimpl->clear (updateKind); }\r
+const ReferenceCountedArray<AudioProcessorGraph::Node>& AudioProcessorGraph::getNodes() const noexcept      { return pimpl->getNodes(); }\r
+AudioProcessorGraph::Node* AudioProcessorGraph::getNodeForId (NodeID x) const                               { return pimpl->getNodeForId (x).get(); }\r
+bool AudioProcessorGraph::disconnectNode (NodeID nodeID, UpdateKind updateKind)                             { return pimpl->disconnectNode (nodeID, updateKind); }\r
+void AudioProcessorGraph::releaseResources()                                                                { return pimpl->releaseResources(); }\r
+bool AudioProcessorGraph::removeIllegalConnections (UpdateKind updateKind)                                  { return pimpl->removeIllegalConnections (updateKind); }\r
+void AudioProcessorGraph::reset()                                                                           { return pimpl->reset(); }\r
+bool AudioProcessorGraph::canConnect (const Connection& c) const                                            { return pimpl->canConnect (c); }\r
+bool AudioProcessorGraph::isConnected (const Connection& c) const noexcept                                  { return pimpl->isConnected (c); }\r
+bool AudioProcessorGraph::isConnected (NodeID a, NodeID b) const noexcept                                   { return pimpl->isConnected (a, b); }\r
+bool AudioProcessorGraph::isConnectionLegal (const Connection& c) const                                     { return pimpl->isConnectionLegal (c); }\r
+bool AudioProcessorGraph::isAnInputTo (const Node& source, const Node& destination) const noexcept          { return pimpl->isAnInputTo (source, destination); }\r
+bool AudioProcessorGraph::isAnInputTo (NodeID source, NodeID destination) const noexcept                    { return pimpl->isAnInputTo (source, destination); }\r
+\r
+AudioProcessorGraph::Node::Ptr AudioProcessorGraph::addNode (std::unique_ptr<AudioProcessor> newProcessor,\r
+                                                             NodeID nodeId,\r
+                                                             UpdateKind updateKind)\r
+{\r
+    return pimpl->addNode (std::move (newProcessor), nodeId, updateKind);\r
 }\r
 \r
-void AudioProcessorGraph::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)\r
+void AudioProcessorGraph::setNonRealtime (bool isProcessingNonRealtime) noexcept\r
 {\r
-    if ((! isPrepared) && MessageManager::getInstance()->isThisTheMessageThread())\r
-        handleAsyncUpdate();\r
+    AudioProcessor::setNonRealtime (isProcessingNonRealtime);\r
+    pimpl->setNonRealtime (isProcessingNonRealtime);\r
+}\r
 \r
-    processBlockForBuffer<float> (buffer, midiMessages, *this, renderSequenceFloat, isPrepared);\r
+AudioProcessorGraph::Node::Ptr AudioProcessorGraph::removeNode (NodeID nodeID, UpdateKind updateKind)\r
+{\r
+    return pimpl->removeNode (nodeID, updateKind);\r
 }\r
 \r
-void AudioProcessorGraph::processBlock (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)\r
+AudioProcessorGraph::Node::Ptr AudioProcessorGraph::removeNode (Node* node, UpdateKind updateKind)\r
 {\r
-    if ((! isPrepared) && MessageManager::getInstance()->isThisTheMessageThread())\r
-        handleAsyncUpdate();\r
+    if (node != nullptr)\r
+        return removeNode (node->nodeID, updateKind);\r
 \r
-    processBlockForBuffer<double> (buffer, midiMessages, *this, renderSequenceDouble, isPrepared);\r
+    jassertfalse;\r
+    return {};\r
 }\r
 \r
 //==============================================================================\r
@@ -1445,9 +1840,7 @@ AudioProcessorGraph::AudioGraphIOProcessor::AudioGraphIOProcessor (const IODevic
 {\r
 }\r
 \r
-AudioProcessorGraph::AudioGraphIOProcessor::~AudioGraphIOProcessor()\r
-{\r
-}\r
+AudioProcessorGraph::AudioGraphIOProcessor::~AudioGraphIOProcessor() = default;\r
 \r
 const String AudioProcessorGraph::AudioGraphIOProcessor::getName() const\r
 {\r
@@ -1499,55 +1892,20 @@ bool AudioProcessorGraph::AudioGraphIOProcessor::supportsDoublePrecisionProcessi
     return true;\r
 }\r
 \r
-template <typename FloatType, typename SequenceType>\r
-static void processIOBlock (AudioProcessorGraph::AudioGraphIOProcessor& io, SequenceType& sequence,\r
-                            AudioBuffer<FloatType>& buffer, MidiBuffer& midiMessages)\r
-{\r
-    switch (io.getType())\r
-    {\r
-        case AudioProcessorGraph::AudioGraphIOProcessor::audioOutputNode:\r
-        {\r
-            auto&& currentAudioOutputBuffer = sequence.currentAudioOutputBuffer;\r
-\r
-            for (int i = jmin (currentAudioOutputBuffer.getNumChannels(), buffer.getNumChannels()); --i >= 0;)\r
-                currentAudioOutputBuffer.addFrom (i, 0, buffer, i, 0, buffer.getNumSamples());\r
-\r
-            break;\r
-        }\r
-\r
-        case AudioProcessorGraph::AudioGraphIOProcessor::audioInputNode:\r
-        {\r
-            auto* currentInputBuffer = sequence.currentAudioInputBuffer;\r
-\r
-            for (int i = jmin (currentInputBuffer->getNumChannels(), buffer.getNumChannels()); --i >= 0;)\r
-                buffer.copyFrom (i, 0, *currentInputBuffer, i, 0, buffer.getNumSamples());\r
-\r
-            break;\r
-        }\r
-\r
-        case AudioProcessorGraph::AudioGraphIOProcessor::midiOutputNode:\r
-            sequence.currentMidiOutputBuffer.addEvents (midiMessages, 0, buffer.getNumSamples(), 0);\r
-            break;\r
-\r
-        case AudioProcessorGraph::AudioGraphIOProcessor::midiInputNode:\r
-            midiMessages.addEvents (*sequence.currentMidiInputBuffer, 0, buffer.getNumSamples(), 0);\r
-            break;\r
-\r
-        default:\r
-            break;\r
-    }\r
-}\r
-\r
 void AudioProcessorGraph::AudioGraphIOProcessor::processBlock (AudioBuffer<float>& buffer, MidiBuffer& midiMessages)\r
 {\r
     jassert (graph != nullptr);\r
-    processIOBlock (*this, *graph->renderSequenceFloat, buffer, midiMessages);\r
+\r
+    if (auto* state = graph->pimpl->getAudioThreadState())\r
+        state->processIO (*this, buffer, midiMessages);\r
 }\r
 \r
 void AudioProcessorGraph::AudioGraphIOProcessor::processBlock (AudioBuffer<double>& buffer, MidiBuffer& midiMessages)\r
 {\r
     jassert (graph != nullptr);\r
-    processIOBlock (*this, *graph->renderSequenceDouble, buffer, midiMessages);\r
+\r
+    if (auto* state = graph->pimpl->getAudioThreadState())\r
+        state->processIO (*this, buffer, midiMessages);\r
 }\r
 \r
 double AudioProcessorGraph::AudioGraphIOProcessor::getTailLengthSeconds() const\r
@@ -1596,4 +1954,166 @@ void AudioProcessorGraph::AudioGraphIOProcessor::setParentGraph (AudioProcessorG
     }\r
 }\r
 \r
+//==============================================================================\r
+//==============================================================================\r
+#if JUCE_UNIT_TESTS\r
+\r
+class AudioProcessorGraphTests : public UnitTest\r
+{\r
+public:\r
+    AudioProcessorGraphTests()\r
+        : UnitTest ("AudioProcessorGraph", UnitTestCategories::audioProcessors) {}\r
+\r
+    void runTest() override\r
+    {\r
+        const auto midiChannel = AudioProcessorGraph::midiChannelIndex;\r
+\r
+        beginTest ("isConnected returns true when two nodes are connected");\r
+        {\r
+            AudioProcessorGraph graph;\r
+            const auto nodeA = graph.addNode (BasicProcessor::make ({}, MidiIn::no, MidiOut::yes))->nodeID;\r
+            const auto nodeB = graph.addNode (BasicProcessor::make ({}, MidiIn::yes, MidiOut::no))->nodeID;\r
+\r
+            expect (graph.canConnect ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+            expect (! graph.canConnect ({ { nodeB, midiChannel }, { nodeA, midiChannel } }));\r
+            expect (! graph.canConnect ({ { nodeA, midiChannel }, { nodeA, midiChannel } }));\r
+            expect (! graph.canConnect ({ { nodeB, midiChannel }, { nodeB, midiChannel } }));\r
+\r
+            expect (graph.getConnections().empty());\r
+            expect (! graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+            expect (! graph.isConnected (nodeA, nodeB));\r
+\r
+            expect (graph.addConnection ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+\r
+            expect (graph.getConnections().size() == 1);\r
+            expect (graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+            expect (graph.isConnected (nodeA, nodeB));\r
+\r
+            expect (graph.disconnectNode (nodeA));\r
+\r
+            expect (graph.getConnections().empty());\r
+            expect (! graph.isConnected ({ { nodeA, midiChannel }, { nodeB, midiChannel } }));\r
+            expect (! graph.isConnected (nodeA, nodeB));\r
+        }\r
+\r
+        beginTest ("graph lookups work with a large number of connections");\r
+        {\r
+            AudioProcessorGraph graph;\r
+\r
+            std::vector<AudioProcessorGraph::NodeID> nodeIDs;\r
+\r
+            constexpr auto numNodes = 100;\r
+\r
+            for (auto i = 0; i < numNodes; ++i)\r
+            {\r
+                nodeIDs.push_back (graph.addNode (BasicProcessor::make (BasicProcessor::getStereoProperties(),\r
+                                                                        MidiIn::yes,\r
+                                                                        MidiOut::yes))->nodeID);\r
+            }\r
+\r
+            for (auto it = nodeIDs.begin(); it != std::prev (nodeIDs.end()); ++it)\r
+            {\r
+                expect (graph.addConnection ({ { it[0], 0 }, { it[1], 0 } }));\r
+                expect (graph.addConnection ({ { it[0], 1 }, { it[1], 1 } }));\r
+            }\r
+\r
+            // Check whether isConnected reports correct results when called\r
+            // with both connections and nodes\r
+            for (auto it = nodeIDs.begin(); it != std::prev (nodeIDs.end()); ++it)\r
+            {\r
+                expect (graph.isConnected ({ { it[0], 0 }, { it[1], 0 } }));\r
+                expect (graph.isConnected ({ { it[0], 1 }, { it[1], 1 } }));\r
+                expect (graph.isConnected (it[0], it[1]));\r
+            }\r
+\r
+            const auto& nodes = graph.getNodes();\r
+\r
+            expect (! graph.isAnInputTo (*nodes[0], *nodes[0]));\r
+\r
+            // Check whether isAnInputTo behaves correctly for a non-cyclic graph\r
+            for (auto it = std::next (nodes.begin()); it != std::prev (nodes.end()); ++it)\r
+            {\r
+                expect (! graph.isAnInputTo (**it, **it));\r
+\r
+                expect (graph.isAnInputTo (*nodes[0], **it));\r
+                expect (! graph.isAnInputTo (**it, *nodes[0]));\r
+\r
+                expect (graph.isAnInputTo (**it, *nodes[nodes.size() - 1]));\r
+                expect (! graph.isAnInputTo (*nodes[nodes.size() - 1], **it));\r
+            }\r
+\r
+            // Make the graph cyclic\r
+            graph.addConnection ({ { nodeIDs.back(), 0 }, { nodeIDs.front(), 0 } });\r
+            graph.addConnection ({ { nodeIDs.back(), 1 }, { nodeIDs.front(), 1 } });\r
+\r
+            // Check whether isAnInputTo behaves correctly for a cyclic graph\r
+            for (const auto* node : graph.getNodes())\r
+            {\r
+                expect (graph.isAnInputTo (*node, *node));\r
+\r
+                expect (graph.isAnInputTo (*nodes[0], *node));\r
+                expect (graph.isAnInputTo (*node, *nodes[0]));\r
+\r
+                expect (graph.isAnInputTo (*node, *nodes[nodes.size() - 1]));\r
+                expect (graph.isAnInputTo (*nodes[nodes.size() - 1], *node));\r
+            }\r
+        }\r
+    }\r
+\r
+private:\r
+    enum class MidiIn  { no, yes };\r
+    enum class MidiOut { no, yes };\r
+\r
+    class BasicProcessor  : public AudioProcessor\r
+    {\r
+    public:\r
+        explicit BasicProcessor (const AudioProcessor::BusesProperties& layout, MidiIn mIn, MidiOut mOut)\r
+            : AudioProcessor (layout), midiIn (mIn), midiOut (mOut) {}\r
+\r
+        const String getName() const override                         { return "Basic Processor"; }\r
+        double getTailLengthSeconds() const override                  { return {}; }\r
+        bool acceptsMidi() const override                             { return midiIn  == MidiIn ::yes; }\r
+        bool producesMidi() const override                            { return midiOut == MidiOut::yes; }\r
+        AudioProcessorEditor* createEditor() override                 { return {}; }\r
+        bool hasEditor() const override                               { return {}; }\r
+        int getNumPrograms() override                                 { return 1; }\r
+        int getCurrentProgram() override                              { return {}; }\r
+        void setCurrentProgram (int) override                         {}\r
+        const String getProgramName (int) override                    { return {}; }\r
+        void changeProgramName (int, const String&) override          {}\r
+        void getStateInformation (juce::MemoryBlock&) override        {}\r
+        void setStateInformation (const void*, int) override          {}\r
+        void prepareToPlay (double, int) override                     {}\r
+        void releaseResources() override                              {}\r
+        void processBlock (AudioBuffer<float>&, MidiBuffer&) override {}\r
+        bool supportsDoublePrecisionProcessing() const override       { return true; }\r
+        bool isMidiEffect() const override                            { return {}; }\r
+        void reset() override                                         {}\r
+        void setNonRealtime (bool) noexcept override                  {}\r
+\r
+        using AudioProcessor::processBlock;\r
+\r
+        static std::unique_ptr<AudioProcessor> make (const BusesProperties& layout,\r
+                                                     MidiIn midiIn,\r
+                                                     MidiOut midiOut)\r
+        {\r
+            return std::make_unique<BasicProcessor> (layout, midiIn, midiOut);\r
+        }\r
+\r
+        static BusesProperties getStereoProperties()\r
+        {\r
+            return BusesProperties().withInput ("in", AudioChannelSet::stereo())\r
+                                    .withOutput ("out", AudioChannelSet::stereo());\r
+        }\r
+\r
+    private:\r
+        MidiIn midiIn;\r
+        MidiOut midiOut;\r
+    };\r
+};\r
+\r
+static AudioProcessorGraphTests audioProcessorGraphTests;\r
+\r
+#endif\r
+\r
 } // namespace juce\r
index 5b6908824b317b70fd65cef9854699993cbf5766..8190d754d4d0260c844e57b722f6a90fdcca78c8 100644 (file)
@@ -43,8 +43,7 @@ namespace juce
     @tags{Audio}\r
 */\r
 class JUCE_API  AudioProcessorGraph   : public AudioProcessor,\r
-                                        public ChangeBroadcaster,\r
-                                        private AsyncUpdater\r
+                                        public ChangeBroadcaster\r
 {\r
 public:\r
     //==============================================================================\r
@@ -81,15 +80,19 @@ public:
     /**\r
         Represents an input or output channel of a node in an AudioProcessorGraph.\r
     */\r
-    struct NodeAndChannel\r
+    class NodeAndChannel\r
     {\r
+        auto tie() const { return std::tie (nodeID, channelIndex); }\r
+\r
+    public:\r
         NodeID nodeID;\r
         int channelIndex;\r
 \r
         bool isMIDI() const noexcept                                    { return channelIndex == midiChannelIndex; }\r
 \r
-        bool operator== (const NodeAndChannel& other) const noexcept    { return nodeID == other.nodeID && channelIndex == other.channelIndex; }\r
-        bool operator!= (const NodeAndChannel& other) const noexcept    { return ! operator== (other); }\r
+        bool operator== (const NodeAndChannel& other) const noexcept    { return tie() == other.tie(); }\r
+        bool operator!= (const NodeAndChannel& other) const noexcept    { return tie() != other.tie(); }\r
+        bool operator<  (const NodeAndChannel& other) const noexcept    { return tie() <  other.tie(); }\r
     };\r
 \r
     //==============================================================================\r
@@ -119,64 +122,55 @@ public:
 \r
         //==============================================================================\r
         /** Returns if the node is bypassed or not. */\r
-        bool isBypassed() const noexcept;\r
+        bool isBypassed() const noexcept\r
+        {\r
+            if (processor != nullptr)\r
+            {\r
+                if (auto* bypassParam = processor->getBypassParameter())\r
+                    return (bypassParam->getValue() != 0.0f);\r
+            }\r
+\r
+            return bypassed;\r
+        }\r
 \r
         /** Tell this node to bypass processing. */\r
-        void setBypassed (bool shouldBeBypassed) noexcept;\r
+        void setBypassed (bool shouldBeBypassed) noexcept\r
+        {\r
+            if (processor != nullptr)\r
+            {\r
+                if (auto* bypassParam = processor->getBypassParameter())\r
+                    bypassParam->setValueNotifyingHost (shouldBeBypassed ? 1.0f : 0.0f);\r
+            }\r
+\r
+            bypassed = shouldBeBypassed;\r
+        }\r
 \r
         //==============================================================================\r
         /** A convenient typedef for referring to a pointer to a node object. */\r
         using Ptr = ReferenceCountedObjectPtr<Node>;\r
 \r
-    private:\r
-        //==============================================================================\r
-        friend class AudioProcessorGraph;\r
-        template <typename Float>\r
-        friend struct GraphRenderSequence;\r
-        template <typename Float>\r
-        friend struct RenderSequenceBuilder;\r
-\r
-        struct Connection\r
-        {\r
-            Node* otherNode;\r
-            int otherChannel, thisChannel;\r
+        /** @internal\r
 \r
-            bool operator== (const Connection&) const noexcept;\r
-        };\r
-\r
-        std::unique_ptr<AudioProcessor> processor;\r
-        Array<Connection> inputs, outputs;\r
-        bool isPrepared = false;\r
-        std::atomic<bool> bypassed { false };\r
-\r
-        Node (NodeID, std::unique_ptr<AudioProcessor>) noexcept;\r
-\r
-        void setParentGraph (AudioProcessorGraph*) const;\r
-        void prepare (double newSampleRate, int newBlockSize, AudioProcessorGraph*, ProcessingPrecision);\r
-        void unprepare();\r
-\r
-        template <typename Sample>\r
-        void callProcessFunction (AudioBuffer<Sample>& audio,\r
-                                  MidiBuffer& midi,\r
-                                  void (AudioProcessor::* function) (AudioBuffer<Sample>&, MidiBuffer&))\r
-        {\r
-            const ScopedLock lock (processorLock);\r
-            (processor.get()->*function) (audio, midi);\r
-        }\r
+            Returns true if setBypassed(true) was called on this node.\r
+            This behaviour is different from isBypassed(), which may additionally return true if\r
+            the node has a bypass parameter that is not set to 0.\r
+        */\r
+        bool userRequestedBypass() const { return bypassed; }\r
 \r
-        template <typename Sample>\r
-        void processBlock (AudioBuffer<Sample>& audio, MidiBuffer& midi)\r
-        {\r
-            callProcessFunction (audio, midi, &AudioProcessor::processBlock);\r
-        }\r
+        /** @internal\r
 \r
-        template <typename Sample>\r
-        void processBlockBypassed (AudioBuffer<Sample>& audio, MidiBuffer& midi)\r
+            To create a new node, use AudioProcessorGraph::addNode.\r
+        */\r
+        Node (NodeID n, std::unique_ptr<AudioProcessor> p) noexcept\r
+            : nodeID (n), processor (std::move (p))\r
         {\r
-            callProcessFunction (audio, midi, &AudioProcessor::processBlockBypassed);\r
+            jassert (processor != nullptr);\r
         }\r
 \r
-        CriticalSection processorLock;\r
+    private:\r
+        //==============================================================================\r
+        std::unique_ptr<AudioProcessor> processor;\r
+        std::atomic<bool> bypassed { false };\r
 \r
         JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Node)\r
     };\r
@@ -207,23 +201,36 @@ public:
         NodeAndChannel destination { {}, 0 };\r
     };\r
 \r
+    //==============================================================================\r
+    /** Indicates how the graph should be updated after a change.\r
+\r
+        If you need to make lots of changes to a graph (e.g. lots of separate calls\r
+        to addNode, addConnection etc.) you can avoid rebuilding the graph on each\r
+        change by using the async update kind.\r
+    */\r
+    enum class UpdateKind\r
+    {\r
+        sync,   ///< Indicates that the graph should be rebuilt immediately after modification.\r
+        async   ///< Indicates that the graph rebuild should be deferred.\r
+    };\r
+\r
     //==============================================================================\r
     /** Deletes all nodes and connections from this graph.\r
         Any processor objects in the graph will be deleted.\r
     */\r
-    void clear();\r
+    void clear (UpdateKind = UpdateKind::sync);\r
 \r
     /** Returns the array of nodes in the graph. */\r
-    const ReferenceCountedArray<Node>& getNodes() const noexcept    { return nodes; }\r
+    const ReferenceCountedArray<Node>& getNodes() const noexcept;\r
 \r
     /** Returns the number of nodes in the graph. */\r
-    int getNumNodes() const noexcept                                { return nodes.size(); }\r
+    int getNumNodes() const noexcept                                { return getNodes().size(); }\r
 \r
     /** Returns a pointer to one of the nodes in the graph.\r
         This will return nullptr if the index is out of range.\r
         @see getNodeForId\r
     */\r
-    Node::Ptr getNode (int index) const noexcept                    { return nodes[index]; }\r
+    Node::Ptr getNode (int index) const noexcept                    { return getNodes()[index]; }\r
 \r
     /** Searches the graph for a node with the given ID number and returns it.\r
         If no such node was found, this returns nullptr.\r
@@ -242,17 +249,17 @@ public:
 \r
         If this succeeds, it returns a pointer to the newly-created node.\r
     */\r
-    Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor, NodeID nodeId = {});\r
+    Node::Ptr addNode (std::unique_ptr<AudioProcessor> newProcessor, NodeID nodeId = {}, UpdateKind = UpdateKind::sync);\r
 \r
     /** Deletes a node within the graph which has the specified ID.\r
         This will also delete any connections that are attached to this node.\r
     */\r
-    Node::Ptr removeNode (NodeID);\r
+    Node::Ptr removeNode (NodeID, UpdateKind = UpdateKind::sync);\r
 \r
     /** Deletes a node within the graph.\r
         This will also delete any connections that are attached to this node.\r
     */\r
-    Node::Ptr removeNode (Node*);\r
+    Node::Ptr removeNode (Node*, UpdateKind = UpdateKind::sync);\r
 \r
     /** Returns the list of connections in the graph. */\r
     std::vector<Connection> getConnections() const;\r
@@ -268,7 +275,12 @@ public:
     /** Does a recursive check to see if there's a direct or indirect series of connections\r
         between these two nodes.\r
     */\r
-    bool isAnInputTo (Node& source, Node& destination) const noexcept;\r
+    bool isAnInputTo (const Node& source, const Node& destination) const noexcept;\r
+\r
+    /** Does a recursive check to see if there's a direct or indirect series of connections\r
+        between these two nodes.\r
+    */\r
+    bool isAnInputTo (NodeID source, NodeID destination) const noexcept;\r
 \r
     /** Returns true if it would be legal to connect the specified points. */\r
     bool canConnect (const Connection&) const;\r
@@ -278,13 +290,13 @@ public:
         If this isn't allowed (e.g. because you're trying to connect a midi channel\r
         to an audio one or other such nonsense), then it'll return false.\r
     */\r
-    bool addConnection (const Connection&);\r
+    bool addConnection (const Connection&, UpdateKind = UpdateKind::sync);\r
 \r
     /** Deletes the given connection. */\r
-    bool removeConnection (const Connection&);\r
+    bool removeConnection (const Connection&, UpdateKind = UpdateKind::sync);\r
 \r
     /** Removes all connections from the specified node. */\r
-    bool disconnectNode (NodeID);\r
+    bool disconnectNode (NodeID, UpdateKind = UpdateKind::sync);\r
 \r
     /** Returns true if the given connection's channel numbers map on to valid\r
         channels at each end.\r
@@ -298,7 +310,7 @@ public:
         This might be useful if some of the processors are doing things like changing\r
         their channel counts, which could render some connections obsolete.\r
     */\r
-    bool removeIllegalConnections();\r
+    bool removeIllegalConnections (UpdateKind = UpdateKind::sync);\r
 \r
     //==============================================================================\r
     /** A special type of AudioProcessor that can live inside an AudioProcessorGraph\r
@@ -412,50 +424,8 @@ public:
     void setStateInformation (const void* data, int sizeInBytes) override;\r
 \r
 private:\r
-    struct PrepareSettings\r
-    {\r
-        ProcessingPrecision precision = ProcessingPrecision::singlePrecision;\r
-        double sampleRate             = 0.0;\r
-        int blockSize                 = 0;\r
-        bool valid                    = false;\r
-\r
-        using Tied = std::tuple<const ProcessingPrecision&,\r
-                                const double&,\r
-                                const int&,\r
-                                const bool&>;\r
-\r
-        Tied tie() const noexcept { return std::tie (precision, sampleRate, blockSize, valid); }\r
-\r
-        bool operator== (const PrepareSettings& other) const noexcept { return tie() == other.tie(); }\r
-        bool operator!= (const PrepareSettings& other) const noexcept { return tie() != other.tie(); }\r
-    };\r
-\r
-    //==============================================================================\r
-    ReferenceCountedArray<Node> nodes;\r
-    NodeID lastNodeID = {};\r
-\r
-    struct RenderSequenceFloat;\r
-    struct RenderSequenceDouble;\r
-    std::unique_ptr<RenderSequenceFloat> renderSequenceFloat;\r
-    std::unique_ptr<RenderSequenceDouble> renderSequenceDouble;\r
-\r
-    PrepareSettings prepareSettings;\r
-\r
-    friend class AudioGraphIOProcessor;\r
-\r
-    std::atomic<bool> isPrepared { false };\r
-\r
-    void topologyChanged();\r
-    void unprepare();\r
-    void handleAsyncUpdate() override;\r
-    void clearRenderingSequence();\r
-    void buildRenderingSequence();\r
-    bool anyNodesNeedPreparing() const noexcept;\r
-    bool isConnected (Node* src, int sourceChannel, Node* dest, int destChannel) const noexcept;\r
-    bool isAnInputTo (Node& src, Node& dst, int recursionCheck) const noexcept;\r
-    bool canConnect (Node* src, int sourceChannel, Node* dest, int destChannel) const noexcept;\r
-    bool isLegal (Node* src, int sourceChannel, Node* dest, int destChannel) const noexcept;\r
-    static void getNodeConnections (Node&, std::vector<Connection>&);\r
+    class Pimpl;\r
+    std::unique_ptr<Pimpl> pimpl;\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (AudioProcessorGraph)\r
 };\r
index 77516239fbd9c954a0d7b67306bd8ee86b697853..251ff76ac3cf91c9481982d8e4871e5c3c25f4b4 100644 (file)
@@ -78,7 +78,7 @@ public:
 \r
             @see latencyChanged\r
         */\r
-        JUCE_NODISCARD ChangeDetails withLatencyChanged           (bool b) const noexcept { return with (&ChangeDetails::latencyChanged,           b); }\r
+        [[nodiscard]] ChangeDetails withLatencyChanged           (bool b) const noexcept { return with (&ChangeDetails::latencyChanged,           b); }\r
 \r
         /** Indicates that some attributes of the AudioProcessor's parameters have changed.\r
 \r
@@ -88,7 +88,7 @@ public:
 \r
             @see parameterInfoChanged\r
         */\r
-        JUCE_NODISCARD ChangeDetails withParameterInfoChanged     (bool b) const noexcept { return with (&ChangeDetails::parameterInfoChanged,     b); }\r
+        [[nodiscard]] ChangeDetails withParameterInfoChanged     (bool b) const noexcept { return with (&ChangeDetails::parameterInfoChanged,     b); }\r
 \r
         /** Indicates that the loaded program has changed.\r
 \r
@@ -97,7 +97,7 @@ public:
 \r
             @see programChanged\r
         */\r
-        JUCE_NODISCARD ChangeDetails withProgramChanged           (bool b) const noexcept { return with (&ChangeDetails::programChanged,           b); }\r
+        [[nodiscard]] ChangeDetails withProgramChanged           (bool b) const noexcept { return with (&ChangeDetails::programChanged,           b); }\r
 \r
         /** Indicates that the plugin state has changed (but not its parameters!).\r
 \r
@@ -110,7 +110,7 @@ public:
 \r
             @see nonParameterStateChanged\r
         */\r
-        JUCE_NODISCARD ChangeDetails withNonParameterStateChanged (bool b) const noexcept { return with (&ChangeDetails::nonParameterStateChanged, b); }\r
+        [[nodiscard]] ChangeDetails withNonParameterStateChanged (bool b) const noexcept { return with (&ChangeDetails::nonParameterStateChanged, b); }\r
 \r
         /** Returns the default set of flags that will be used when\r
             AudioProcessor::updateHostDisplay() is called with no arguments.\r
index ad90849480eae9dc462f3b0ae873f837eb8f1710..d153c3d28912728399be46dab961efada84abc1a 100644 (file)
@@ -102,6 +102,8 @@ class ParameterComponent : public Component,
 {\r
 public:\r
     using ParameterListener::ParameterListener;\r
+\r
+    JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ParameterComponent)\r
 };\r
 \r
 //==============================================================================\r
index 0485808ddbe3af747d8f6f2d33aca48e07b419ce..f72d160ca638762d3de973207e546bd5886ce8af 100644 (file)
@@ -32,7 +32,7 @@ namespace juce
 \r
     @tags{Audio}\r
 */\r
-struct HostedAudioProcessorParameter : public AudioProcessorParameter\r
+struct JUCE_API  HostedAudioProcessorParameter : public AudioProcessorParameter\r
 {\r
     using AudioProcessorParameter::AudioProcessorParameter;\r
 \r
index dc7414c5b3ed1a8c29fafa0509324c50f41be9e7..6e819cda74f65009f605d2f52a153c8511b34014 100644 (file)
@@ -834,138 +834,122 @@ ARAEditorView* ARADocumentControllerSpecialisation::doCreateEditorView()
     return new ARAEditorView (getDocumentController());\r
 }\r
 \r
-bool ARADocumentControllerSpecialisation::doIsAudioSourceContentAvailable (const ARA::PlugIn::AudioSource* audioSource,\r
-                                                                           ARA::ARAContentType type)\r
+bool ARADocumentControllerSpecialisation::doIsAudioSourceContentAvailable ([[maybe_unused]] const ARA::PlugIn::AudioSource* audioSource,\r
+                                                                           [[maybe_unused]] ARA::ARAContentType type)\r
 {\r
-    juce::ignoreUnused (audioSource, type);\r
     return false;\r
 }\r
 \r
-ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetAudioSourceContentGrade (const ARA::PlugIn::AudioSource* audioSource,\r
-                                                                                        ARA::ARAContentType type)\r
+ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetAudioSourceContentGrade ([[maybe_unused]] const ARA::PlugIn::AudioSource* audioSource,\r
+                                                                                        [[maybe_unused]] ARA::ARAContentType type)\r
 {\r
     // Overriding doIsAudioSourceContentAvailable() requires overriding\r
     // doGetAudioSourceContentGrade() accordingly!\r
     jassertfalse;\r
 \r
-    juce::ignoreUnused (audioSource, type);\r
     return ARA::kARAContentGradeInitial;\r
 }\r
 \r
-ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreateAudioSourceContentReader (ARA::PlugIn::AudioSource* audioSource,\r
-                                                                                                   ARA::ARAContentType type,\r
-                                                                                                   const ARA::ARAContentTimeRange* range)\r
+ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreateAudioSourceContentReader ([[maybe_unused]] ARA::PlugIn::AudioSource* audioSource,\r
+                                                                                                   [[maybe_unused]] ARA::ARAContentType type,\r
+                                                                                                   [[maybe_unused]] const ARA::ARAContentTimeRange* range)\r
 {\r
     // Overriding doIsAudioSourceContentAvailable() requires overriding\r
     // doCreateAudioSourceContentReader() accordingly!\r
     jassertfalse;\r
 \r
-    juce::ignoreUnused (audioSource, type, range);\r
     return nullptr;\r
 }\r
 \r
-bool ARADocumentControllerSpecialisation::doIsAudioModificationContentAvailable (const ARA::PlugIn::AudioModification* audioModification,\r
-                                                                                 ARA::ARAContentType type)\r
+bool ARADocumentControllerSpecialisation::doIsAudioModificationContentAvailable ([[maybe_unused]] const ARA::PlugIn::AudioModification* audioModification,\r
+                                                                                 [[maybe_unused]] ARA::ARAContentType type)\r
 {\r
-    juce::ignoreUnused (audioModification, type);\r
     return false;\r
 }\r
 \r
-ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetAudioModificationContentGrade (const ARA::PlugIn::AudioModification* audioModification,\r
-                                                                                              ARA::ARAContentType type)\r
+ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetAudioModificationContentGrade ([[maybe_unused]] const ARA::PlugIn::AudioModification* audioModification,\r
+                                                                                              [[maybe_unused]] ARA::ARAContentType type)\r
 {\r
     // Overriding doIsAudioModificationContentAvailable() requires overriding\r
     // doGetAudioModificationContentGrade() accordingly!\r
     jassertfalse;\r
 \r
-    juce::ignoreUnused (audioModification, type);\r
     return ARA::kARAContentGradeInitial;\r
 }\r
 \r
-ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreateAudioModificationContentReader (ARA::PlugIn::AudioModification* audioModification,\r
-                                                                                                         ARA::ARAContentType type,\r
-                                                                                                         const ARA::ARAContentTimeRange* range)\r
+ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreateAudioModificationContentReader ([[maybe_unused]] ARA::PlugIn::AudioModification* audioModification,\r
+                                                                                                         [[maybe_unused]] ARA::ARAContentType type,\r
+                                                                                                         [[maybe_unused]] const ARA::ARAContentTimeRange* range)\r
 {\r
     // Overriding doIsAudioModificationContentAvailable() requires overriding\r
     // doCreateAudioModificationContentReader() accordingly!\r
     jassertfalse;\r
 \r
-    juce::ignoreUnused (audioModification, type, range);\r
     return nullptr;\r
 }\r
 \r
-bool ARADocumentControllerSpecialisation::doIsPlaybackRegionContentAvailable (const ARA::PlugIn::PlaybackRegion* playbackRegion,\r
-                                                                              ARA::ARAContentType type)\r
+bool ARADocumentControllerSpecialisation::doIsPlaybackRegionContentAvailable ([[maybe_unused]] const ARA::PlugIn::PlaybackRegion* playbackRegion,\r
+                                                                              [[maybe_unused]] ARA::ARAContentType type)\r
 {\r
-    juce::ignoreUnused (playbackRegion, type);\r
     return false;\r
 }\r
 \r
-ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetPlaybackRegionContentGrade (const ARA::PlugIn::PlaybackRegion* playbackRegion,\r
-                                                                                           ARA::ARAContentType type)\r
+ARA::ARAContentGrade ARADocumentControllerSpecialisation::doGetPlaybackRegionContentGrade ([[maybe_unused]] const ARA::PlugIn::PlaybackRegion* playbackRegion,\r
+                                                                                           [[maybe_unused]] ARA::ARAContentType type)\r
 {\r
     // Overriding doIsPlaybackRegionContentAvailable() requires overriding\r
     // doGetPlaybackRegionContentGrade() accordingly!\r
     jassertfalse;\r
 \r
-    juce::ignoreUnused (playbackRegion, type);\r
     return ARA::kARAContentGradeInitial;\r
 }\r
 \r
-ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreatePlaybackRegionContentReader (ARA::PlugIn::PlaybackRegion* playbackRegion,\r
-                                                                                                      ARA::ARAContentType type,\r
-                                                                                                      const ARA::ARAContentTimeRange* range)\r
+ARA::PlugIn::ContentReader* ARADocumentControllerSpecialisation::doCreatePlaybackRegionContentReader ([[maybe_unused]] ARA::PlugIn::PlaybackRegion* playbackRegion,\r
+                                                                                                      [[maybe_unused]] ARA::ARAContentType type,\r
+                                                                                                      [[maybe_unused]] const ARA::ARAContentTimeRange* range)\r
 {\r
     // Overriding doIsPlaybackRegionContentAvailable() requires overriding\r
     // doCreatePlaybackRegionContentReader() accordingly!\r
     jassertfalse;\r
 \r
-    juce::ignoreUnused (playbackRegion, type, range);\r
     return nullptr;\r
 }\r
 \r
-bool ARADocumentControllerSpecialisation::doIsAudioSourceContentAnalysisIncomplete (const ARA::PlugIn::AudioSource* audioSource,\r
-                                                                                    ARA::ARAContentType type)\r
+bool ARADocumentControllerSpecialisation::doIsAudioSourceContentAnalysisIncomplete ([[maybe_unused]] const ARA::PlugIn::AudioSource* audioSource,\r
+                                                                                    [[maybe_unused]] ARA::ARAContentType type)\r
 {\r
-    juce::ignoreUnused (audioSource, type);\r
     return false;\r
 }\r
 \r
-void ARADocumentControllerSpecialisation::doRequestAudioSourceContentAnalysis (ARA::PlugIn::AudioSource* audioSource,\r
-                                                                               std::vector<ARA::ARAContentType> const& contentTypes)\r
+void ARADocumentControllerSpecialisation::doRequestAudioSourceContentAnalysis ([[maybe_unused]] ARA::PlugIn::AudioSource* audioSource,\r
+                                                                               [[maybe_unused]] std::vector<ARA::ARAContentType> const& contentTypes)\r
 {\r
-    juce::ignoreUnused (audioSource, contentTypes);\r
 }\r
 \r
 ARA::ARAInt32 ARADocumentControllerSpecialisation::doGetProcessingAlgorithmsCount() { return 0; }\r
 \r
 const ARA::ARAProcessingAlgorithmProperties*\r
-    ARADocumentControllerSpecialisation::doGetProcessingAlgorithmProperties (ARA::ARAInt32 algorithmIndex)\r
+    ARADocumentControllerSpecialisation::doGetProcessingAlgorithmProperties ([[maybe_unused]] ARA::ARAInt32 algorithmIndex)\r
 {\r
-    juce::ignoreUnused (algorithmIndex);\r
     return nullptr;\r
 }\r
 \r
-ARA::ARAInt32 ARADocumentControllerSpecialisation::doGetProcessingAlgorithmForAudioSource (const ARA::PlugIn::AudioSource* audioSource)\r
+ARA::ARAInt32 ARADocumentControllerSpecialisation::doGetProcessingAlgorithmForAudioSource ([[maybe_unused]] const ARA::PlugIn::AudioSource* audioSource)\r
 {\r
     // doGetProcessingAlgorithmForAudioSource() must be implemented if the supported\r
     // algorithm count is greater than zero.\r
     if (getDocumentController()->getProcessingAlgorithmsCount() > 0)\r
         jassertfalse;\r
 \r
-    juce::ignoreUnused (audioSource);\r
     return 0;\r
 }\r
 \r
-void ARADocumentControllerSpecialisation::doRequestProcessingAlgorithmForAudioSource (ARA::PlugIn::AudioSource* audioSource,\r
-                                                                                      ARA::ARAInt32 algorithmIndex)\r
+void ARADocumentControllerSpecialisation::doRequestProcessingAlgorithmForAudioSource ([[maybe_unused]] ARA::PlugIn::AudioSource* audioSource,\r
+                                                                                      [[maybe_unused]] ARA::ARAInt32 algorithmIndex)\r
 {\r
     // doRequestProcessingAlgorithmForAudioSource() must be implemented if the supported\r
     // algorithm count is greater than zero.\r
-    if (getDocumentController()->getProcessingAlgorithmsCount() > 0)\r
-        jassertfalse;\r
-\r
-    juce::ignoreUnused (audioSource, algorithmIndex);\r
+    jassert (getDocumentController()->getProcessingAlgorithmsCount() <= 0);\r
 }\r
 \r
 } // namespace juce\r
index b06a83122f43ee811e26dd19a36ef740a381c940..8b04fbb0ca0da78c7f51122e46c684f45a3466d2 100644 (file)
@@ -123,7 +123,7 @@ public:
     template <typename SpecialisationType>\r
     static const ARA::ARAFactory* createARAFactory()\r
     {\r
-        static_assert (std::is_base_of<ARADocumentControllerSpecialisation, SpecialisationType>::value,\r
+        static_assert (std::is_base_of_v<ARADocumentControllerSpecialisation, SpecialisationType>,\r
                        "DocumentController specialization types must inherit from ARADocumentControllerSpecialisation");\r
         return ARA::PlugIn::PlugInEntry::getPlugInEntry<FactoryConfig<SpecialisationType>>()->getFactory();\r
     }\r
index 918aee434e7efe9c85a13b65a5cc40d6e45e03d4..3db14330272b8005106c0929ef44bfc2bf732139 100644 (file)
@@ -196,4 +196,98 @@ void ARAPlaybackRegion::notifyContentChanged (ARAContentUpdateScopes scopeFlags,
                                                                                                 notifyARAHost);\r
 }\r
 \r
+//==============================================================================\r
+void ARADocumentListener::willBeginEditing ([[maybe_unused]] ARADocument* document) {}\r
+void ARADocumentListener::didEndEditing ([[maybe_unused]] ARADocument* document) {}\r
+void ARADocumentListener::willNotifyModelUpdates ([[maybe_unused]] ARADocument* document) {}\r
+void ARADocumentListener::didNotifyModelUpdates ([[maybe_unused]] ARADocument* document) {}\r
+void ARADocumentListener::willUpdateDocumentProperties ([[maybe_unused]] ARADocument* document,\r
+                                                        [[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARADocumentProperties> newProperties) {}\r
+void ARADocumentListener::didUpdateDocumentProperties ([[maybe_unused]] ARADocument* document) {}\r
+void ARADocumentListener::didAddMusicalContextToDocument ([[maybe_unused]] ARADocument* document,\r
+                                                          [[maybe_unused]] ARAMusicalContext* musicalContext) {}\r
+void ARADocumentListener::willRemoveMusicalContextFromDocument ([[maybe_unused]] ARADocument* document,\r
+                                                                [[maybe_unused]] ARAMusicalContext* musicalContext) {}\r
+void ARADocumentListener::didReorderMusicalContextsInDocument ([[maybe_unused]] ARADocument* document) {}\r
+void ARADocumentListener::didAddRegionSequenceToDocument ([[maybe_unused]] ARADocument* document,\r
+                                                          [[maybe_unused]] ARARegionSequence* regionSequence) {}\r
+void ARADocumentListener::willRemoveRegionSequenceFromDocument ([[maybe_unused]] ARADocument* document,\r
+                                                                [[maybe_unused]] ARARegionSequence* regionSequence) {}\r
+void ARADocumentListener::didReorderRegionSequencesInDocument ([[maybe_unused]] ARADocument* document) {}\r
+void ARADocumentListener::didAddAudioSourceToDocument ([[maybe_unused]] ARADocument* document,\r
+                                                       [[maybe_unused]] ARAAudioSource* audioSource) {}\r
+void ARADocumentListener::willRemoveAudioSourceFromDocument ([[maybe_unused]] ARADocument* document,\r
+                                                             [[maybe_unused]] ARAAudioSource* audioSource) {}\r
+void ARADocumentListener::willDestroyDocument ([[maybe_unused]] ARADocument* document) {}\r
+\r
+//==============================================================================\r
+void ARAMusicalContextListener::willUpdateMusicalContextProperties ([[maybe_unused]] ARAMusicalContext* musicalContext,\r
+                                                                    [[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARAMusicalContextProperties> newProperties) {}\r
+void ARAMusicalContextListener::didUpdateMusicalContextProperties ([[maybe_unused]] ARAMusicalContext* musicalContext) {}\r
+void ARAMusicalContextListener::doUpdateMusicalContextContent ([[maybe_unused]] ARAMusicalContext* musicalContext,\r
+                                                               [[maybe_unused]] ARAContentUpdateScopes scopeFlags) {}\r
+void ARAMusicalContextListener::didAddRegionSequenceToMusicalContext ([[maybe_unused]] ARAMusicalContext* musicalContext,\r
+                                                                      [[maybe_unused]] ARARegionSequence* regionSequence) {}\r
+void ARAMusicalContextListener::willRemoveRegionSequenceFromMusicalContext ([[maybe_unused]] ARAMusicalContext* musicalContext,\r
+                                                                            [[maybe_unused]] ARARegionSequence* regionSequence) {}\r
+void ARAMusicalContextListener::didReorderRegionSequencesInMusicalContext ([[maybe_unused]] ARAMusicalContext* musicalContext) {}\r
+void ARAMusicalContextListener::willDestroyMusicalContext ([[maybe_unused]] ARAMusicalContext* musicalContext) {}\r
+\r
+//==============================================================================\r
+void ARAPlaybackRegionListener::willUpdatePlaybackRegionProperties ([[maybe_unused]] ARAPlaybackRegion* playbackRegion,\r
+                                                                    [[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARAPlaybackRegionProperties> newProperties) {}\r
+void ARAPlaybackRegionListener::didUpdatePlaybackRegionProperties ([[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}\r
+void ARAPlaybackRegionListener::didUpdatePlaybackRegionContent ([[maybe_unused]] ARAPlaybackRegion* playbackRegion,\r
+                                                                [[maybe_unused]] ARAContentUpdateScopes scopeFlags) {}\r
+void ARAPlaybackRegionListener::willDestroyPlaybackRegion ([[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}\r
+\r
+//==============================================================================\r
+void ARARegionSequenceListener::willUpdateRegionSequenceProperties ([[maybe_unused]] ARARegionSequence* regionSequence,\r
+                                                                    [[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARARegionSequenceProperties> newProperties) {}\r
+void ARARegionSequenceListener::didUpdateRegionSequenceProperties ([[maybe_unused]] ARARegionSequence* regionSequence) {}\r
+void ARARegionSequenceListener::willRemovePlaybackRegionFromRegionSequence ([[maybe_unused]] ARARegionSequence* regionSequence,\r
+                                                                            [[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}\r
+void ARARegionSequenceListener::didAddPlaybackRegionToRegionSequence ([[maybe_unused]] ARARegionSequence* regionSequence,\r
+                                                                      [[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}\r
+void ARARegionSequenceListener::willDestroyRegionSequence ([[maybe_unused]] ARARegionSequence* regionSequence) {}\r
+\r
+//==============================================================================\r
+void ARAAudioSourceListener::willUpdateAudioSourceProperties ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                              [[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARAAudioSourceProperties> newProperties) {}\r
+void ARAAudioSourceListener::didUpdateAudioSourceProperties ([[maybe_unused]] ARAAudioSource* audioSource) {}\r
+void ARAAudioSourceListener::doUpdateAudioSourceContent ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                         [[maybe_unused]] ARAContentUpdateScopes scopeFlags) {}\r
+void ARAAudioSourceListener::didUpdateAudioSourceAnalysisProgress ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                                   [[maybe_unused]] ARA::ARAAnalysisProgressState state,\r
+                                                                   [[maybe_unused]] float progress) {}\r
+void ARAAudioSourceListener::willEnableAudioSourceSamplesAccess ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                                 [[maybe_unused]] bool enable) {}\r
+void ARAAudioSourceListener::didEnableAudioSourceSamplesAccess ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                                [[maybe_unused]] bool enable) {}\r
+void ARAAudioSourceListener::willDeactivateAudioSourceForUndoHistory ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                                      [[maybe_unused]] bool deactivate) {}\r
+void ARAAudioSourceListener::didDeactivateAudioSourceForUndoHistory ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                                     [[maybe_unused]] bool deactivate) {}\r
+void ARAAudioSourceListener::didAddAudioModificationToAudioSource ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                                   [[maybe_unused]] ARAAudioModification* audioModification) {}\r
+void ARAAudioSourceListener::willRemoveAudioModificationFromAudioSource ([[maybe_unused]] ARAAudioSource* audioSource,\r
+                                                                         [[maybe_unused]] ARAAudioModification* audioModification) {}\r
+void ARAAudioSourceListener::willDestroyAudioSource ([[maybe_unused]] ARAAudioSource* audioSource) {}\r
+\r
+//==============================================================================\r
+void ARAAudioModificationListener::willUpdateAudioModificationProperties ([[maybe_unused]] ARAAudioModification* audioModification,\r
+                                                                          [[maybe_unused]] ARA::PlugIn::PropertiesPtr<ARA::ARAAudioModificationProperties> newProperties) {}\r
+void ARAAudioModificationListener::didUpdateAudioModificationProperties ([[maybe_unused]] ARAAudioModification* audioModification) {}\r
+void ARAAudioModificationListener::didUpdateAudioModificationContent ([[maybe_unused]] ARAAudioModification* audioModification,\r
+                                                                      [[maybe_unused]] ARAContentUpdateScopes scopeFlags) {}\r
+void ARAAudioModificationListener::willDeactivateAudioModificationForUndoHistory ([[maybe_unused]] ARAAudioModification* audioModification,\r
+                                                                                  [[maybe_unused]] bool deactivate) {}\r
+void ARAAudioModificationListener::didDeactivateAudioModificationForUndoHistory ([[maybe_unused]] ARAAudioModification* audioModification,\r
+                                                                                 [[maybe_unused]] bool deactivate) {}\r
+void ARAAudioModificationListener::didAddPlaybackRegionToAudioModification ([[maybe_unused]] ARAAudioModification* audioModification,\r
+                                                                            [[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}\r
+void ARAAudioModificationListener::willRemovePlaybackRegionFromAudioModification ([[maybe_unused]] ARAAudioModification* audioModification,\r
+                                                                                  [[maybe_unused]] ARAPlaybackRegion* playbackRegion) {}\r
+void ARAAudioModificationListener::willDestroyAudioModification ([[maybe_unused]] ARAAudioModification* audioModification) {}\r
+\r
 } // namespace juce\r
index e5434e3c7bfab3e31ff70fc3a5233c0356c80467..2f3096f2f8141f02150f352ece17aa1ba03a1d49 100644 (file)
@@ -181,76 +181,49 @@ public:
     /** Destructor */\r
     virtual ~ARADocumentListener() = default;\r
 \r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN\r
-\r
     /** Called before the document enters an editing state.\r
         @param document The document about to enter an editing state.\r
     */\r
-    virtual void willBeginEditing (ARADocument* document)\r
-    {\r
-        ignoreUnused (document);\r
-    }\r
+    virtual void willBeginEditing (ARADocument* document);\r
 \r
     /** Called after the document exits an editing state.\r
         @param document The document about exit an editing state.\r
     */\r
-    virtual void didEndEditing (ARADocument* document)\r
-    {\r
-        ignoreUnused (document);\r
-    }\r
+    virtual void didEndEditing (ARADocument* document);\r
 \r
     /** Called before sending model updates do the host.\r
         @param document The document whose model updates are about to be sent.\r
     */\r
-    virtual void willNotifyModelUpdates (ARADocument* document)\r
-    {\r
-        ignoreUnused (document);\r
-    }\r
+    virtual void willNotifyModelUpdates (ARADocument* document);\r
 \r
     /** Called after sending model updates do the host.\r
         @param document The document whose model updates have just been sent.\r
     */\r
-    virtual void didNotifyModelUpdates (ARADocument* document)\r
-    {\r
-        ignoreUnused (document);\r
-    }\r
+    virtual void didNotifyModelUpdates (ARADocument* document);\r
 \r
     /** Called before the document's properties are updated.\r
         @param document The document whose properties will be updated.\r
         @param newProperties The document properties that will be assigned to \p document.\r
     */\r
     virtual void willUpdateDocumentProperties (ARADocument* document,\r
-                                               ARA::PlugIn::PropertiesPtr<ARA::ARADocumentProperties> newProperties)\r
-    {\r
-        ignoreUnused (document, newProperties);\r
-    }\r
+                                               ARA::PlugIn::PropertiesPtr<ARA::ARADocumentProperties> newProperties);\r
 \r
     /** Called after the document's properties are updated.\r
         @param document The document whose properties were updated.\r
     */\r
-    virtual void didUpdateDocumentProperties (ARADocument* document)\r
-    {\r
-        ignoreUnused (document);\r
-    }\r
+    virtual void didUpdateDocumentProperties (ARADocument* document);\r
 \r
     /** Called after a musical context is added to the document.\r
         @param document The document that \p musicalContext was added to.\r
         @param musicalContext The musical context that was added to \p document.\r
     */\r
-    virtual void didAddMusicalContextToDocument (ARADocument* document, ARAMusicalContext* musicalContext)\r
-    {\r
-        ignoreUnused (document, musicalContext);\r
-    }\r
+    virtual void didAddMusicalContextToDocument (ARADocument* document, ARAMusicalContext* musicalContext);\r
 \r
     /** Called before a musical context is removed from the document.\r
         @param document The document that \p musicalContext will be removed from.\r
         @param musicalContext The musical context that will be removed from \p document.\r
     */\r
-    virtual void willRemoveMusicalContextFromDocument (ARADocument* document,\r
-                                                       ARAMusicalContext* musicalContext)\r
-    {\r
-        ignoreUnused (document, musicalContext);\r
-    }\r
+    virtual void willRemoveMusicalContextFromDocument (ARADocument* document, ARAMusicalContext* musicalContext);\r
 \r
     /** Called after the musical contexts are reordered in an ARA document\r
 \r
@@ -259,29 +232,19 @@ public:
 \r
         @param document The document with reordered musical contexts.\r
     */\r
-    virtual void didReorderMusicalContextsInDocument (ARADocument* document)\r
-    {\r
-        ignoreUnused (document);\r
-    }\r
+    virtual void didReorderMusicalContextsInDocument (ARADocument* document);\r
 \r
     /** Called after a region sequence is added to the document.\r
         @param document The document that \p regionSequence was added to.\r
         @param regionSequence The region sequence that was added to \p document.\r
     */\r
-    virtual void didAddRegionSequenceToDocument (ARADocument* document, ARARegionSequence* regionSequence)\r
-    {\r
-        ignoreUnused (document, regionSequence);\r
-    }\r
+    virtual void didAddRegionSequenceToDocument (ARADocument* document, ARARegionSequence* regionSequence);\r
 \r
     /** Called before a region sequence is removed from the document.\r
         @param document The document that \p regionSequence will be removed from.\r
         @param regionSequence The region sequence that will be removed from \p document.\r
     */\r
-    virtual void willRemoveRegionSequenceFromDocument (ARADocument* document,\r
-                                                       ARARegionSequence* regionSequence)\r
-    {\r
-        ignoreUnused (document, regionSequence);\r
-    }\r
+    virtual void willRemoveRegionSequenceFromDocument (ARADocument* document, ARARegionSequence* regionSequence);\r
 \r
     /** Called after the region sequences are reordered in an ARA document\r
 \r
@@ -290,38 +253,24 @@ public:
 \r
         @param document The document with reordered region sequences.\r
     */\r
-    virtual void didReorderRegionSequencesInDocument (ARADocument* document)\r
-    {\r
-        ignoreUnused (document);\r
-    }\r
+    virtual void didReorderRegionSequencesInDocument (ARADocument* document);\r
 \r
     /** Called after an audio source is added to the document.\r
         @param document The document that \p audioSource was added to.\r
         @param audioSource The audio source that was added to \p document.\r
     */\r
-    virtual void didAddAudioSourceToDocument (ARADocument* document, ARAAudioSource* audioSource)\r
-    {\r
-        ignoreUnused (document, audioSource);\r
-    }\r
+    virtual void didAddAudioSourceToDocument (ARADocument* document, ARAAudioSource* audioSource);\r
 \r
     /** Called before an audio source is removed from the document.\r
         @param document The document that \p audioSource will be removed from .\r
         @param audioSource The audio source that will be removed from \p document.\r
     */\r
-    virtual void willRemoveAudioSourceFromDocument (ARADocument* document, ARAAudioSource* audioSource)\r
-    {\r
-        ignoreUnused (document, audioSource);\r
-    }\r
+    virtual void willRemoveAudioSourceFromDocument (ARADocument* document, ARAAudioSource* audioSource);\r
 \r
     /** Called before the document is destroyed by the ARA host.\r
         @param document The document that will be destroyed.\r
     */\r
-    virtual void willDestroyDocument (ARADocument* document)\r
-    {\r
-        ignoreUnused (document);\r
-    }\r
-\r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END\r
+    virtual void willDestroyDocument (ARADocument* document);\r
 };\r
 \r
 //==============================================================================\r
@@ -395,55 +344,36 @@ class JUCE_API  ARAMusicalContextListener
 public:\r
     virtual ~ARAMusicalContextListener() = default;\r
 \r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN\r
-\r
     /** Called before the musical context's properties are updated.\r
         @param musicalContext The musical context whose properties will be updated.\r
         @param newProperties The musical context properties that will be assigned to \p musicalContext.\r
     */\r
     virtual void willUpdateMusicalContextProperties (ARAMusicalContext* musicalContext,\r
-                                                     ARA::PlugIn::PropertiesPtr<ARA::ARAMusicalContextProperties> newProperties)\r
-    {\r
-        ignoreUnused (musicalContext, newProperties);\r
-    }\r
+                                                     ARA::PlugIn::PropertiesPtr<ARA::ARAMusicalContextProperties> newProperties);\r
 \r
     /** Called after the musical context's properties are updated by the host.\r
         @param musicalContext The musical context whose properties were updated.\r
     */\r
-    virtual void didUpdateMusicalContextProperties (ARAMusicalContext* musicalContext)\r
-    {\r
-        ignoreUnused (musicalContext);\r
-    }\r
+    virtual void didUpdateMusicalContextProperties (ARAMusicalContext* musicalContext);\r
 \r
     /** Called when the musical context's content (i.e tempo entries or chords) changes.\r
         @param musicalContext The musical context with updated content.\r
         @param scopeFlags The scope of the content update indicating what has changed.\r
     */\r
-    virtual void doUpdateMusicalContextContent (ARAMusicalContext* musicalContext,\r
-                                                ARAContentUpdateScopes scopeFlags)\r
-    {\r
-        ignoreUnused (musicalContext, scopeFlags);\r
-    }\r
+    virtual void doUpdateMusicalContextContent (ARAMusicalContext* musicalContext, ARAContentUpdateScopes scopeFlags);\r
 \r
     /** Called after a region sequence is added to the musical context.\r
         @param musicalContext The musical context that \p regionSequence was added to.\r
         @param regionSequence The region sequence that was added to \p musicalContext.\r
     */\r
-    virtual void didAddRegionSequenceToMusicalContext (ARAMusicalContext* musicalContext,\r
-                                                       ARARegionSequence* regionSequence)\r
-    {\r
-        ignoreUnused (musicalContext, regionSequence);\r
-    }\r
+    virtual void didAddRegionSequenceToMusicalContext (ARAMusicalContext* musicalContext, ARARegionSequence* regionSequence);\r
 \r
     /** Called before a region sequence is removed from the musical context.\r
         @param musicalContext The musical context that \p regionSequence will be removed from.\r
         @param regionSequence The region sequence that will be removed from \p musicalContext.\r
     */\r
     virtual void willRemoveRegionSequenceFromMusicalContext (ARAMusicalContext* musicalContext,\r
-                                                             ARARegionSequence* regionSequence)\r
-    {\r
-        ignoreUnused (musicalContext, regionSequence);\r
-    }\r
+                                                             ARARegionSequence* regionSequence);\r
 \r
     /** Called after the region sequences are reordered in an ARA MusicalContext\r
 \r
@@ -452,20 +382,12 @@ public:
 \r
         @param musicalContext The musical context with reordered region sequences.\r
     */\r
-    virtual void didReorderRegionSequencesInMusicalContext (ARAMusicalContext* musicalContext)\r
-    {\r
-        ignoreUnused (musicalContext);\r
-    }\r
+    virtual void didReorderRegionSequencesInMusicalContext (ARAMusicalContext* musicalContext);\r
 \r
     /** Called before the musical context is destroyed.\r
         @param musicalContext The musical context that will be destroyed.\r
     */\r
-    virtual void willDestroyMusicalContext (ARAMusicalContext* musicalContext)\r
-    {\r
-        ignoreUnused (musicalContext);\r
-    }\r
-\r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END\r
+    virtual void willDestroyMusicalContext (ARAMusicalContext* musicalContext);\r
 };\r
 \r
 //==============================================================================\r
@@ -528,45 +450,29 @@ public:
     /** Destructor. */\r
     virtual ~ARAPlaybackRegionListener() = default;\r
 \r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN\r
-\r
     /** Called before the playback region's properties are updated.\r
         @param playbackRegion The playback region whose properties will be updated.\r
         @param newProperties The playback region properties that will be assigned to \p playbackRegion.\r
     */\r
     virtual void willUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion,\r
-                                                     ARA::PlugIn::PropertiesPtr<ARA::ARAPlaybackRegionProperties> newProperties)\r
-    {\r
-        ignoreUnused (playbackRegion, newProperties);\r
-    }\r
+                                                     ARA::PlugIn::PropertiesPtr<ARA::ARAPlaybackRegionProperties> newProperties);\r
 \r
     /** Called after the playback region's properties are updated.\r
         @param playbackRegion The playback region whose properties were updated.\r
     */\r
-    virtual void didUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion)\r
-    {\r
-        ignoreUnused (playbackRegion);\r
-    }\r
+    virtual void didUpdatePlaybackRegionProperties (ARAPlaybackRegion* playbackRegion);\r
 \r
     /** Called when the playback region's content (i.e. samples or notes) changes.\r
         @param playbackRegion The playback region with updated content.\r
         @param scopeFlags The scope of the content update.\r
     */\r
     virtual void didUpdatePlaybackRegionContent (ARAPlaybackRegion* playbackRegion,\r
-                                                 ARAContentUpdateScopes scopeFlags)\r
-    {\r
-        ignoreUnused (playbackRegion, scopeFlags);\r
-    }\r
+                                                 ARAContentUpdateScopes scopeFlags);\r
 \r
     /** Called before the playback region is destroyed.\r
         @param playbackRegion The playback region that will be destroyed.\r
     */\r
-    virtual void willDestroyPlaybackRegion (ARAPlaybackRegion* playbackRegion)\r
-    {\r
-        ignoreUnused (playbackRegion);\r
-    }\r
-\r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END\r
+    virtual void willDestroyPlaybackRegion (ARAPlaybackRegion* playbackRegion);\r
 };\r
 \r
 //==============================================================================\r
@@ -665,55 +571,36 @@ public:
     /** Destructor. */\r
     virtual ~ARARegionSequenceListener() = default;\r
 \r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN\r
-\r
     /** Called before the region sequence's properties are updated.\r
         @param regionSequence The region sequence whose properties will be updated.\r
         @param newProperties The region sequence properties that will be assigned to \p regionSequence.\r
     */\r
     virtual void willUpdateRegionSequenceProperties (ARARegionSequence* regionSequence,\r
-                                                     ARA::PlugIn::PropertiesPtr<ARA::ARARegionSequenceProperties> newProperties)\r
-    {\r
-        ignoreUnused (regionSequence, newProperties);\r
-    }\r
+                                                     ARA::PlugIn::PropertiesPtr<ARA::ARARegionSequenceProperties> newProperties);\r
 \r
     /** Called after the region sequence's properties are updated.\r
         @param regionSequence The region sequence whose properties were updated.\r
     */\r
-    virtual void didUpdateRegionSequenceProperties (ARARegionSequence* regionSequence)\r
-    {\r
-        ignoreUnused (regionSequence);\r
-    }\r
+    virtual void didUpdateRegionSequenceProperties (ARARegionSequence* regionSequence);\r
 \r
     /** Called before a playback region is removed from the region sequence.\r
         @param regionSequence The region sequence that \p playbackRegion will be removed from.\r
         @param playbackRegion The playback region that will be removed from \p regionSequence.\r
     */\r
     virtual void willRemovePlaybackRegionFromRegionSequence (ARARegionSequence* regionSequence,\r
-                                                             ARAPlaybackRegion* playbackRegion)\r
-    {\r
-        ignoreUnused (regionSequence, playbackRegion);\r
-    }\r
+                                                             ARAPlaybackRegion* playbackRegion);\r
 \r
     /** Called after a playback region is added to the region sequence.\r
         @param regionSequence The region sequence that \p playbackRegion was added to.\r
         @param playbackRegion The playback region that was added to \p regionSequence.\r
     */\r
     virtual void didAddPlaybackRegionToRegionSequence (ARARegionSequence* regionSequence,\r
-                                                       ARAPlaybackRegion* playbackRegion)\r
-    {\r
-        ignoreUnused (regionSequence, playbackRegion);\r
-    }\r
+                                                       ARAPlaybackRegion* playbackRegion);\r
 \r
     /** Called before the region sequence is destroyed.\r
         @param regionSequence The region sequence that will be destroyed.\r
     */\r
-    virtual void willDestroyRegionSequence (ARARegionSequence* regionSequence)\r
-    {\r
-        ignoreUnused (regionSequence);\r
-    }\r
-\r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END\r
+    virtual void willDestroyRegionSequence (ARARegionSequence* regionSequence);\r
 };\r
 \r
 //==============================================================================\r
@@ -800,34 +687,23 @@ public:
     /** Destructor. */\r
     virtual ~ARAAudioSourceListener() = default;\r
 \r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN\r
-\r
     /** Called before the audio source's properties are updated.\r
         @param audioSource The audio source whose properties will be updated.\r
         @param newProperties The audio source properties that will be assigned to \p audioSource.\r
     */\r
     virtual void willUpdateAudioSourceProperties (ARAAudioSource* audioSource,\r
-                                                  ARA::PlugIn::PropertiesPtr<ARA::ARAAudioSourceProperties> newProperties)\r
-    {\r
-        ignoreUnused (audioSource, newProperties);\r
-    }\r
+                                                  ARA::PlugIn::PropertiesPtr<ARA::ARAAudioSourceProperties> newProperties);\r
 \r
     /** Called after the audio source's properties are updated.\r
         @param audioSource The audio source whose properties were updated.\r
     */\r
-    virtual void didUpdateAudioSourceProperties (ARAAudioSource* audioSource)\r
-    {\r
-        ignoreUnused (audioSource);\r
-    }\r
+    virtual void didUpdateAudioSourceProperties (ARAAudioSource* audioSource);\r
 \r
     /** Called when the audio source's content (i.e. samples or notes) changes.\r
         @param audioSource The audio source with updated content.\r
         @param scopeFlags The scope of the content update.\r
     */\r
-    virtual void doUpdateAudioSourceContent (ARAAudioSource* audioSource, ARAContentUpdateScopes scopeFlags)\r
-    {\r
-        ignoreUnused (audioSource, scopeFlags);\r
-    }\r
+    virtual void doUpdateAudioSourceContent (ARAAudioSource* audioSource, ARAContentUpdateScopes scopeFlags);\r
 \r
     /** Called to notify progress when an audio source is being analyzed.\r
         @param audioSource The audio source being analyzed.\r
@@ -836,76 +712,54 @@ public:
     */\r
     virtual void didUpdateAudioSourceAnalysisProgress (ARAAudioSource* audioSource,\r
                                                        ARA::ARAAnalysisProgressState state,\r
-                                                       float progress)\r
-    {\r
-        ignoreUnused (audioSource, state, progress);\r
-    }\r
+                                                       float progress);\r
 \r
     /** Called before access to an audio source's samples is enabled or disabled.\r
         @param audioSource The audio source whose sample access state will be changed.\r
         @param enable A bool indicating whether or not sample access will be enabled or disabled.\r
     */\r
-    virtual void willEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource, bool enable)\r
-    {\r
-        ignoreUnused (audioSource, enable);\r
-    }\r
+    virtual void willEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource,\r
+                                                     bool enable);\r
 \r
     /** Called after access to an audio source's samples is enabled or disabled.\r
         @param audioSource The audio source whose sample access state was changed.\r
         @param enable A bool indicating whether or not sample access was enabled or disabled.\r
     */\r
-    virtual void didEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource, bool enable)\r
-    {\r
-        ignoreUnused (audioSource, enable);\r
-    }\r
+    virtual void didEnableAudioSourceSamplesAccess (ARAAudioSource* audioSource,\r
+                                                    bool enable);\r
 \r
     /** Called before an audio source is activated or deactivated when being removed / added from the host's undo history.\r
         @param audioSource The audio source that will be activated or deactivated\r
         @param deactivate A bool indicating whether \p audioSource was deactivated or activated.\r
     */\r
-    virtual void willDeactivateAudioSourceForUndoHistory (ARAAudioSource* audioSource, bool deactivate)\r
-    {\r
-        ignoreUnused (audioSource, deactivate);\r
-    }\r
+    virtual void willDeactivateAudioSourceForUndoHistory (ARAAudioSource* audioSource,\r
+                                                          bool deactivate);\r
 \r
     /** Called after an audio source is activated or deactivated when being removed / added from the host's undo history.\r
         @param audioSource The audio source that was activated or deactivated\r
         @param deactivate A bool indicating whether \p audioSource was deactivated or activated.\r
     */\r
-    virtual void didDeactivateAudioSourceForUndoHistory (ARAAudioSource* audioSource, bool deactivate)\r
-    {\r
-        ignoreUnused (audioSource, deactivate);\r
-    }\r
+    virtual void didDeactivateAudioSourceForUndoHistory (ARAAudioSource* audioSource,\r
+                                                         bool deactivate);\r
 \r
     /** Called after an audio modification is added to the audio source.\r
         @param audioSource The region sequence that \p audioModification was added to.\r
         @param audioModification The playback region that was added to \p audioSource.\r
     */\r
     virtual void didAddAudioModificationToAudioSource (ARAAudioSource* audioSource,\r
-                                                       ARAAudioModification* audioModification)\r
-    {\r
-        ignoreUnused (audioSource, audioModification);\r
-    }\r
+                                                       ARAAudioModification* audioModification);\r
 \r
     /** Called before an audio modification is removed from the audio source.\r
         @param audioSource The audio source that \p audioModification will be removed from.\r
         @param audioModification The audio modification that will be removed from \p audioSource.\r
     */\r
     virtual void willRemoveAudioModificationFromAudioSource (ARAAudioSource* audioSource,\r
-                                                             ARAAudioModification* audioModification)\r
-    {\r
-        ignoreUnused (audioSource, audioModification);\r
-    }\r
+                                                             ARAAudioModification* audioModification);\r
 \r
     /** Called before the audio source is destroyed.\r
         @param audioSource The audio source that will be destroyed.\r
     */\r
-    virtual void willDestroyAudioSource (ARAAudioSource* audioSource)\r
-    {\r
-        ignoreUnused (audioSource);\r
-    }\r
-\r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END\r
+    virtual void willDestroyAudioSource (ARAAudioSource* audioSource);\r
 };\r
 \r
 //==============================================================================\r
@@ -1004,82 +858,57 @@ public:
     /** Destructor. */\r
     virtual ~ARAAudioModificationListener() = default;\r
 \r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN\r
-\r
     /** Called before the audio modification's properties are updated.\r
         @param audioModification The audio modification whose properties will be updated.\r
         @param newProperties The audio modification properties that will be assigned to \p audioModification.\r
     */\r
     virtual void willUpdateAudioModificationProperties (ARAAudioModification* audioModification,\r
-                                                        ARA::PlugIn::PropertiesPtr<ARA::ARAAudioModificationProperties> newProperties)\r
-    {\r
-        ignoreUnused (audioModification, newProperties);\r
-    }\r
+                                                        ARA::PlugIn::PropertiesPtr<ARA::ARAAudioModificationProperties> newProperties);\r
 \r
     /** Called after the audio modification's properties are updated.\r
         @param audioModification The audio modification whose properties were updated.\r
     */\r
-    virtual void didUpdateAudioModificationProperties (ARAAudioModification* audioModification)\r
-    {\r
-        ignoreUnused (audioModification);\r
-    }\r
+    virtual void didUpdateAudioModificationProperties (ARAAudioModification* audioModification);\r
 \r
     /** Called when the audio modification's content (i.e. samples or notes) changes.\r
         @param audioModification The audio modification with updated content.\r
         @param scopeFlags The scope of the content update.\r
     */\r
-    virtual void didUpdateAudioModificationContent (ARAAudioModification* audioModification, ARAContentUpdateScopes scopeFlags)\r
-    {\r
-        ignoreUnused (audioModification, scopeFlags);\r
-    }\r
+    virtual void didUpdateAudioModificationContent (ARAAudioModification* audioModification,\r
+                                                    ARAContentUpdateScopes scopeFlags);\r
 \r
     /** Called before an audio modification is activated or deactivated when being removed / added from the host's undo history.\r
         @param audioModification The audio modification that was activated or deactivated\r
         @param deactivate A bool indicating whether \p audioModification was deactivated or activated.\r
     */\r
-    virtual void willDeactivateAudioModificationForUndoHistory (ARAAudioModification* audioModification, bool deactivate)\r
-    {\r
-        ignoreUnused (audioModification, deactivate);\r
-    }\r
+    virtual void willDeactivateAudioModificationForUndoHistory (ARAAudioModification* audioModification,\r
+                                                                bool deactivate);\r
 \r
     /** Called after an audio modification is activated or deactivated when being removed / added from the host's undo history.\r
         @param audioModification The audio modification that was activated or deactivated\r
         @param deactivate A bool indicating whether \p audioModification was deactivated or activated.\r
     */\r
-    virtual void didDeactivateAudioModificationForUndoHistory (ARAAudioModification* audioModification, bool deactivate)\r
-    {\r
-        ignoreUnused (audioModification, deactivate);\r
-    }\r
+    virtual void didDeactivateAudioModificationForUndoHistory (ARAAudioModification* audioModification,\r
+                                                               bool deactivate);\r
 \r
     /** Called after a playback region is added to the audio modification.\r
         @param audioModification The audio modification that \p playbackRegion was added to.\r
         @param playbackRegion The playback region that was added to \p audioModification.\r
     */\r
     virtual void didAddPlaybackRegionToAudioModification (ARAAudioModification* audioModification,\r
-                                                          ARAPlaybackRegion* playbackRegion)\r
-    {\r
-        ignoreUnused (audioModification, playbackRegion);\r
-    }\r
+                                                          ARAPlaybackRegion* playbackRegion);\r
 \r
     /** Called before a playback region is removed from the audio modification.\r
         @param audioModification The audio modification that \p playbackRegion will be removed from.\r
         @param playbackRegion The playback region that will be removed from \p audioModification.\r
     */\r
     virtual void willRemovePlaybackRegionFromAudioModification (ARAAudioModification* audioModification,\r
-                                                                ARAPlaybackRegion* playbackRegion)\r
-    {\r
-        ignoreUnused (audioModification, playbackRegion);\r
-    }\r
+                                                                ARAPlaybackRegion* playbackRegion);\r
 \r
     /** Called before the audio modification is destroyed.\r
         @param audioModification The audio modification that will be destroyed.\r
     */\r
-    virtual void willDestroyAudioModification (ARAAudioModification* audioModification)\r
-    {\r
-        ignoreUnused (audioModification);\r
-    }\r
-\r
-   ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END\r
+    virtual void willDestroyAudioModification (ARAAudioModification* audioModification);\r
 };\r
 \r
 //==============================================================================\r
index fcece498b55a0c60a92ce59aa2f1717f5b9c1f45..c80e1027d66213e2eb40d5bd741437aceb37ec86 100644 (file)
 namespace juce\r
 {\r
 \r
-bool ARARenderer::processBlock (AudioBuffer<double>& buffer,\r
-                                AudioProcessor::Realtime realtime,\r
-                                const AudioPlayHead::PositionInfo& positionInfo) noexcept\r
+bool ARARenderer::processBlock ([[maybe_unused]] AudioBuffer<double>& buffer,\r
+                                [[maybe_unused]] AudioProcessor::Realtime realtime,\r
+                                [[maybe_unused]] const AudioPlayHead::PositionInfo& positionInfo) noexcept\r
 {\r
-    ignoreUnused (buffer, realtime, positionInfo);\r
-\r
     // If you hit this assertion then either the caller called the double\r
     // precision version of processBlock on a processor which does not support it\r
     // (i.e. supportsDoublePrecisionProcessing() returns false), or the implementation\r
@@ -43,6 +41,12 @@ bool ARARenderer::processBlock (AudioBuffer<double>& buffer,
     return false;\r
 }\r
 \r
+void ARARenderer::prepareToPlay ([[maybe_unused]] double sampleRate,\r
+                                 [[maybe_unused]] int maximumSamplesPerBlock,\r
+                                 [[maybe_unused]] int numChannels,\r
+                                 [[maybe_unused]] AudioProcessor::ProcessingPrecision precision,\r
+                                 [[maybe_unused]] AlwaysNonRealtime alwaysNonRealtime) {}\r
+\r
 //==============================================================================\r
 #if ARA_VALIDATE_API_CALLS\r
 void ARAPlaybackRenderer::addPlaybackRegion (ARA::ARAPlaybackRegionRef playbackRegionRef) noexcept\r
@@ -62,6 +66,21 @@ void ARAPlaybackRenderer::removePlaybackRegion (ARA::ARAPlaybackRegionRef playba
 }\r
 #endif\r
 \r
+bool ARAPlaybackRenderer::processBlock ([[maybe_unused]] AudioBuffer<float>& buffer,\r
+                                        [[maybe_unused]] AudioProcessor::Realtime realtime,\r
+                                        [[maybe_unused]] const AudioPlayHead::PositionInfo& positionInfo) noexcept\r
+{\r
+    return false;\r
+}\r
+\r
+//==============================================================================\r
+bool ARAEditorRenderer::processBlock ([[maybe_unused]] AudioBuffer<float>& buffer,\r
+                                      [[maybe_unused]] AudioProcessor::Realtime isNonRealtime,\r
+                                      [[maybe_unused]] const AudioPlayHead::PositionInfo& positionInfo) noexcept\r
+{\r
+    return true;\r
+}\r
+\r
 //==============================================================================\r
 void ARAEditorView::doNotifySelection (const ARA::PlugIn::ViewSelection* viewSelection) noexcept\r
 {\r
@@ -89,4 +108,7 @@ void ARAEditorView::removeListener (Listener* l)
     listeners.remove (l);\r
 }\r
 \r
+void ARAEditorView::Listener::onNewSelection ([[maybe_unused]] const ARAViewSelection& viewSelection) {}\r
+void ARAEditorView::Listener::onHideRegionSequences ([[maybe_unused]] const std::vector<ARARegionSequence*>& regionSequences) {}\r
+\r
 } // namespace juce\r
index e23aeded75bbd527a812fd4f8af7f3d3b363f4ff..490e56670fce4c0eaa4699920a7d2e775156d0c7 100644 (file)
@@ -59,10 +59,7 @@ public:
                                 int maximumSamplesPerBlock,\r
                                 int numChannels,\r
                                 AudioProcessor::ProcessingPrecision precision,\r
-                                AlwaysNonRealtime alwaysNonRealtime = AlwaysNonRealtime::no)\r
-    {\r
-        ignoreUnused (sampleRate, maximumSamplesPerBlock, numChannels, precision, alwaysNonRealtime);\r
-    }\r
+                                AlwaysNonRealtime alwaysNonRealtime = AlwaysNonRealtime::no);\r
 \r
     /** Frees render resources allocated in prepareToPlay(). */\r
     virtual void releaseResources() {}\r
@@ -128,11 +125,7 @@ public:
 \r
     bool processBlock (AudioBuffer<float>& buffer,\r
                        AudioProcessor::Realtime realtime,\r
-                       const AudioPlayHead::PositionInfo& positionInfo) noexcept override\r
-    {\r
-        ignoreUnused (buffer, realtime, positionInfo);\r
-        return false;\r
-    }\r
+                       const AudioPlayHead::PositionInfo& positionInfo) noexcept override;\r
 \r
     using ARARenderer::processBlock;\r
 \r
@@ -191,11 +184,7 @@ public:
     // isNonRealtime of the process context - typically preview is limited to realtime.\r
     bool processBlock (AudioBuffer<float>& buffer,\r
                        AudioProcessor::Realtime isNonRealtime,\r
-                       const AudioPlayHead::PositionInfo& positionInfo) noexcept override\r
-    {\r
-        ignoreUnused (buffer, isNonRealtime, positionInfo);\r
-        return true;\r
-    }\r
+                       const AudioPlayHead::PositionInfo& positionInfo) noexcept override;\r
 \r
     using ARARenderer::processBlock;\r
 \r
@@ -204,7 +193,7 @@ private:
 };\r
 \r
 //==============================================================================\r
-/** Base class for a renderer fulfilling the ARAEditorView role as described in the ARA SDK.\r
+/** Base class for fulfilling the ARAEditorView role as described in the ARA SDK.\r
 \r
     Instances of this class are constructed by the DocumentController. If you are subclassing\r
     ARAEditorView, make sure to call the base class implementation of overridden functions.\r
@@ -218,7 +207,7 @@ public:
 \r
     // Shadowing templated getters to default to JUCE versions of the returned classes\r
     template <typename RegionSequence_t = ARARegionSequence>\r
-    std::vector<RegionSequence_t*> const& getHiddenRegionSequences() const noexcept\r
+    const std::vector<RegionSequence_t*>& getHiddenRegionSequences() const noexcept\r
     {\r
         return ARA::PlugIn::EditorView::getHiddenRegionSequences<RegionSequence_t>();\r
     }\r
@@ -227,7 +216,7 @@ public:
     void doNotifySelection (const ARA::PlugIn::ViewSelection* currentSelection) noexcept override;\r
 \r
     // Base class implementation must be called if overridden\r
-    void doNotifyHideRegionSequences (std::vector<ARA::PlugIn::RegionSequence*> const& regionSequences) noexcept override;\r
+    void doNotifyHideRegionSequences (const std::vector<ARA::PlugIn::RegionSequence*>& regionSequences) noexcept override;\r
 \r
     /** A base class for listeners that want to know about changes to an ARAEditorView object.\r
 \r
@@ -239,25 +228,15 @@ public:
         /** Destructor. */\r
         virtual ~Listener() = default;\r
 \r
-       ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_BEGIN\r
-\r
         /** Called when the editor view's selection changes.\r
             @param viewSelection The current selection state\r
         */\r
-        virtual void onNewSelection (const ARA::PlugIn::ViewSelection& viewSelection)\r
-        {\r
-            ignoreUnused (viewSelection);\r
-        }\r
+        virtual void onNewSelection (const ARAViewSelection& viewSelection);\r
 \r
         /** Called when region sequences are flagged as hidden in the host UI.\r
             @param regionSequences A vector containing all hidden region sequences.\r
         */\r
-        virtual void onHideRegionSequences (std::vector<ARARegionSequence*> const& regionSequences)\r
-        {\r
-            ignoreUnused (regionSequences);\r
-        }\r
-\r
-       ARA_DISABLE_UNREFERENCED_PARAMETER_WARNING_END\r
+        virtual void onHideRegionSequences (const std::vector<ARARegionSequence*>& regionSequences);\r
     };\r
 \r
     /** \copydoc ARAListenableModelClass::addListener */\r
index a75834c8beb370600fe06f487c07c8af96a28a55..15f7882c9ff824a45c8d154f126127c7a83b7c13 100644 (file)
@@ -71,34 +71,34 @@ public:
     using Category = AudioProcessorParameter::Category;\r
 \r
     /** An optional label for the parameter's value */\r
-    JUCE_NODISCARD auto withLabel (String x)            const { return withMember (*this, &This::label,          std::move (x)); }\r
+    [[nodiscard]] auto withLabel (String x)            const { return withMember (*this, &This::label,          std::move (x)); }\r
 \r
     /** The semantics of this parameter */\r
-    JUCE_NODISCARD auto withCategory (Category x)       const { return withMember (*this, &This::category,       std::move (x)); }\r
+    [[nodiscard]] auto withCategory (Category x)       const { return withMember (*this, &This::category,       std::move (x)); }\r
 \r
     /** @see AudioProcessorParameter::isMetaParameter() */\r
-    JUCE_NODISCARD auto withMeta (bool x)               const { return withMember (*this, &This::meta,           std::move (x)); }\r
+    [[nodiscard]] auto withMeta (bool x)               const { return withMember (*this, &This::meta,           std::move (x)); }\r
 \r
     /** @see AudioProcessorParameter::isAutomatable() */\r
-    JUCE_NODISCARD auto withAutomatable (bool x)        const { return withMember (*this, &This::automatable,    std::move (x)); }\r
+    [[nodiscard]] auto withAutomatable (bool x)        const { return withMember (*this, &This::automatable,    std::move (x)); }\r
 \r
     /** @see AudioProcessorParameter::isOrientationInverted() */\r
-    JUCE_NODISCARD auto withInverted (bool x)           const { return withMember (*this, &This::inverted,       std::move (x)); }\r
+    [[nodiscard]] auto withInverted (bool x)           const { return withMember (*this, &This::inverted,       std::move (x)); }\r
 \r
     /** An optional label for the parameter's value */\r
-    JUCE_NODISCARD auto getLabel()                      const { return label; }\r
+    [[nodiscard]] auto getLabel()                      const { return label; }\r
 \r
     /** The semantics of this parameter */\r
-    JUCE_NODISCARD auto getCategory()                   const { return category; }\r
+    [[nodiscard]] auto getCategory()                   const { return category; }\r
 \r
     /** @see AudioProcessorParameter::isMetaParameter() */\r
-    JUCE_NODISCARD auto getMeta()                       const { return meta; }\r
+    [[nodiscard]] auto getMeta()                       const { return meta; }\r
 \r
     /** @see AudioProcessorParameter::isAutomatable() */\r
-    JUCE_NODISCARD auto getAutomatable()                const { return automatable; }\r
+    [[nodiscard]] auto getAutomatable()                const { return automatable; }\r
 \r
     /** @see AudioProcessorParameter::isOrientationInverted() */\r
-    JUCE_NODISCARD auto getInverted()                   const { return inverted; }\r
+    [[nodiscard]] auto getInverted()                   const { return inverted; }\r
 \r
 private:\r
     String label;\r
index caf7eb79891a68c7cc4c906daa5350cf265d2658..7e75bc145886a72c149636fb48c661db038c0db9 100644 (file)
@@ -251,7 +251,7 @@ AudioProcessorValueTreeState::AudioProcessorValueTreeState (AudioProcessor& proc
                 }\r
             }\r
 \r
-            state->processor.addParameterGroup (move (group));\r
+            state->processor.addParameterGroup (std::move (group));\r
         }\r
 \r
         AudioProcessorValueTreeState* state;\r
index 4c498f9b28c1ea12d2ad4a73790709d04af42306..a6e0de39476cb46d5613e55f5e7c2bd455ed8a29 100644 (file)
@@ -42,38 +42,38 @@ class AudioProcessorValueTreeStateParameterAttributes
 \r
 public:\r
     /** @see RangedAudioParameterAttributes::withStringFromValueFunction() */\r
-    JUCE_NODISCARD auto withStringFromValueFunction (StringFromValue x) const { return withMember (*this, &This::attributes, attributes.withStringFromValueFunction (std::move (x))); }\r
+    [[nodiscard]] auto withStringFromValueFunction (StringFromValue x) const { return withMember (*this, &This::attributes, attributes.withStringFromValueFunction (std::move (x))); }\r
     /** @see RangedAudioParameterAttributes::withValueFromStringFunction() */\r
-    JUCE_NODISCARD auto withValueFromStringFunction (ValueFromString x) const { return withMember (*this, &This::attributes, attributes.withValueFromStringFunction (std::move (x))); }\r
+    [[nodiscard]] auto withValueFromStringFunction (ValueFromString x) const { return withMember (*this, &This::attributes, attributes.withValueFromStringFunction (std::move (x))); }\r
     /** @see RangedAudioParameterAttributes::withLabel() */\r
-    JUCE_NODISCARD auto withLabel (String x)                            const { return withMember (*this, &This::attributes, attributes.withLabel                   (std::move (x))); }\r
+    [[nodiscard]] auto withLabel (String x)                            const { return withMember (*this, &This::attributes, attributes.withLabel                   (std::move (x))); }\r
     /** @see RangedAudioParameterAttributes::withCategory() */\r
-    JUCE_NODISCARD auto withCategory (Category x)                       const { return withMember (*this, &This::attributes, attributes.withCategory                (std::move (x))); }\r
+    [[nodiscard]] auto withCategory (Category x)                       const { return withMember (*this, &This::attributes, attributes.withCategory                (std::move (x))); }\r
     /** @see RangedAudioParameterAttributes::withMeta() */\r
-    JUCE_NODISCARD auto withMeta (bool x)                               const { return withMember (*this, &This::attributes, attributes.withMeta                    (std::move (x))); }\r
+    [[nodiscard]] auto withMeta (bool x)                               const { return withMember (*this, &This::attributes, attributes.withMeta                    (std::move (x))); }\r
     /** @see RangedAudioParameterAttributes::withAutomatable() */\r
-    JUCE_NODISCARD auto withAutomatable (bool x)                        const { return withMember (*this, &This::attributes, attributes.withAutomatable             (std::move (x))); }\r
+    [[nodiscard]] auto withAutomatable (bool x)                        const { return withMember (*this, &This::attributes, attributes.withAutomatable             (std::move (x))); }\r
     /** @see RangedAudioParameterAttributes::withInverted() */\r
-    JUCE_NODISCARD auto withInverted (bool x)                           const { return withMember (*this, &This::attributes, attributes.withInverted                (std::move (x))); }\r
+    [[nodiscard]] auto withInverted (bool x)                           const { return withMember (*this, &This::attributes, attributes.withInverted                (std::move (x))); }\r
 \r
     /** Pass 'true' if this parameter has discrete steps, or 'false' if the parameter is continuous.\r
 \r
         Using an AudioParameterChoice or AudioParameterInt might be a better choice than setting this flag.\r
     */\r
-    JUCE_NODISCARD auto withDiscrete (bool x)                           const { return withMember (*this, &This::discrete,   std::move (x)); }\r
+    [[nodiscard]] auto withDiscrete (bool x)                           const { return withMember (*this, &This::discrete,   std::move (x)); }\r
 \r
     /** Pass 'true' if this parameter only has two valid states.\r
 \r
         Using an AudioParameterBool might be a better choice than setting this flag.\r
     */\r
-    JUCE_NODISCARD auto withBoolean (bool x)                            const { return withMember (*this, &This::boolean,    std::move (x)); }\r
+    [[nodiscard]] auto withBoolean (bool x)                            const { return withMember (*this, &This::boolean,    std::move (x)); }\r
 \r
     /** @returns all attributes that might also apply to an AudioParameterFloat */\r
-    JUCE_NODISCARD const auto& getAudioParameterFloatAttributes()       const { return attributes; }\r
+    [[nodiscard]] const auto& getAudioParameterFloatAttributes()       const { return attributes; }\r
     /** @returns 'true' if this parameter has discrete steps, or 'false' if the parameter is continuous. */\r
-    JUCE_NODISCARD const auto& getDiscrete()                            const { return discrete; }\r
+    [[nodiscard]] const auto& getDiscrete()                            const { return discrete; }\r
     /** @returns 'true' if this parameter only has two valid states. */\r
-    JUCE_NODISCARD const auto& getBoolean()                             const { return boolean; }\r
+    [[nodiscard]] const auto& getBoolean()                             const { return boolean; }\r
 \r
 private:\r
     AudioParameterFloatAttributes attributes;\r
@@ -135,12 +135,7 @@ public:
         void add (std::unique_ptr<Items>... items)\r
         {\r
             parameters.reserve (parameters.size() + sizeof... (items));\r
-\r
-            // We can replace this with some nicer code once generic lambdas become available. A\r
-            // sequential context like an array initialiser is required to ensure we get the correct\r
-            // order from the parameter pack.\r
-            int unused[] { (parameters.emplace_back (MakeContents() (std::move (items))), 0)... };\r
-            ignoreUnused (unused);\r
+            (parameters.push_back (makeParameterStorage (std::move (items))), ...);\r
         }\r
 \r
         template <typename It, typename = ValidIfIterator<It>>\r
@@ -150,7 +145,7 @@ public:
             std::transform (std::make_move_iterator (begin),\r
                             std::make_move_iterator (end),\r
                             std::back_inserter (parameters),\r
-                            MakeContents());\r
+                            [] (auto item) { return makeParameterStorage (std::move (item)); });\r
         }\r
 \r
         ParameterLayout (const ParameterLayout& other) = delete;\r
@@ -191,14 +186,11 @@ public:
             std::unique_ptr<Contents> contents;\r
         };\r
 \r
-        struct MakeContents final\r
+        template <typename Contents>\r
+        static std::unique_ptr<ParameterStorage<Contents>> makeParameterStorage (std::unique_ptr<Contents> contents)\r
         {\r
-            template <typename Item>\r
-            std::unique_ptr<ParameterStorageBase> operator() (std::unique_ptr<Item> item) const\r
-            {\r
-                return std::unique_ptr<ParameterStorageBase> (new ParameterStorage<Item> (std::move (item)));\r
-            }\r
-        };\r
+            return std::make_unique<ParameterStorage<Contents>> (std::move (contents));\r
+        }\r
 \r
         void add() {}\r
 \r
@@ -498,7 +490,7 @@ public:
                          valueRange,\r
                          defaultParameterValue,\r
                          AudioProcessorValueTreeStateParameterAttributes().withLabel (labelText)\r
-                                                                          .withStringFromValueFunction ([valueToTextFunction] (float v, int) { return valueToTextFunction (v); })\r
+                                                                          .withStringFromValueFunction (adaptSignature (std::move (valueToTextFunction)))\r
                                                                           .withValueFromStringFunction (std::move (textToValueFunction))\r
                                                                           .withMeta (isMetaParameter)\r
                                                                           .withAutomatable (isAutomatableParameter)\r
@@ -515,6 +507,14 @@ public:
         bool isBoolean() const override;\r
 \r
     private:\r
+        static std::function<String (float, int)> adaptSignature (std::function<String (float)> func)\r
+        {\r
+            if (func == nullptr)\r
+                return nullptr;\r
+\r
+            return [func = std::move (func)] (float v, int) { return func (v); };\r
+        }\r
+\r
         void valueChanged (float) override;\r
 \r
         std::function<void()> onValueChanged;\r
index 6651bddf848cf6b3916c875f684ec94ed2100338..78f7ea2346cac7b1c3e9cb3c240b5455f5e03e37 100644 (file)
@@ -56,7 +56,7 @@ void PluginHostType::switchToHostApplication() const
    #endif\r
 }\r
 \r
-bool PluginHostType::isInAAXAudioSuite (AudioProcessor& processor)\r
+bool PluginHostType::isInAAXAudioSuite ([[maybe_unused]] AudioProcessor& processor)\r
 {\r
    #if JucePlugin_Build_AAX\r
     if (PluginHostType::getPluginLoadedAs() == AudioProcessor::wrapperType_AAX\r
@@ -66,14 +66,11 @@ bool PluginHostType::isInAAXAudioSuite (AudioProcessor& processor)
     }\r
    #endif\r
 \r
-    ignoreUnused (processor);\r
     return false;\r
 }\r
 \r
-Image PluginHostType::getHostIcon (int size) const\r
+Image PluginHostType::getHostIcon ([[maybe_unused]] int size) const\r
 {\r
-    ignoreUnused (size);\r
-\r
    #if JucePlugin_Enable_IAA && JucePlugin_Build_Standalone && JUCE_IOS && (! JUCE_USE_CUSTOM_PLUGIN_STANDALONE_APP)\r
     if (isInterAppAudioConnected())\r
         return juce_getIAAHostIcon (size);\r
@@ -101,10 +98,12 @@ const char* PluginHostType::getHostDescription() const noexcept
         case AdobeAudition:            return "Adobe Audition";\r
         case AdobePremierePro:         return "Adobe Premiere";\r
         case AppleGarageBand:          return "Apple GarageBand";\r
+        case AppleInfoHelper:          return "com.apple.audio.InfoHelper";\r
         case AppleLogic:               return "Apple Logic";\r
         case AppleMainStage:           return "Apple MainStage";\r
         case Ardour:                   return "Ardour";\r
         case AULab:                    return "AU Lab";\r
+        case AUVal:                    return "auval";\r
         case AvidProTools:             return "ProTools";\r
         case BitwigStudio:             return "Bitwig Studio";\r
         case CakewalkSonar8:           return "Cakewalk Sonar 8";\r
@@ -215,6 +214,8 @@ PluginHostType::HostType PluginHostType::getHostType()
     if (hostFilename.containsIgnoreCase   ("pluginval"))                return pluginval;\r
     if (hostFilename.containsIgnoreCase   ("AudioPluginHost"))          return JUCEPluginHost;\r
     if (hostFilename.containsIgnoreCase   ("Vienna Ensemble Pro"))      return ViennaEnsemblePro;\r
+    if (hostFilename.containsIgnoreCase   ("auvaltool"))                return AUVal;\r
+    if (hostFilename.containsIgnoreCase   ("com.apple.audio.infohelper")) return AppleInfoHelper;\r
 \r
     if (hostIdReportedByWrapper == "com.apple.logic.pro")               return AppleLogic;\r
     if (hostIdReportedByWrapper == "com.apple.garageband")              return AppleGarageBand;\r
index c222899fd41b15966933cfe1218af07d48ce4da9..cf5f0e405b441ce5b4ac236f01d0cdea45b66460 100644 (file)
@@ -58,10 +58,12 @@ public:
         AdobeAudition,              /**< Represents Adobe Audition. */\r
         AdobePremierePro,           /**< Represents Adobe Premiere Pro. */\r
         AppleGarageBand,            /**< Represents Apple GarageBand. */\r
+        AppleInfoHelper,            /**< Represents Apple com.apple.audio.InfoHelper. */\r
         AppleLogic,                 /**< Represents Apple Logic Pro. */\r
         AppleMainStage,             /**< Represents Apple Main Stage. */\r
         Ardour,                     /**< Represents Ardour. */\r
         AULab,                      /**< Represents AU Lab. */\r
+        AUVal,                      /**< Represents Apple AU validator. */\r
         AvidProTools,               /**< Represents Avid Pro Tools. */\r
         BitwigStudio,               /**< Represents Bitwig Studio. */\r
         CakewalkSonar8,             /**< Represents Cakewalk Sonar 8. */\r
@@ -121,10 +123,14 @@ public:
                                                       || type == AbletonLiveGeneric; }\r
     /** Returns true if the host is Adobe Audition. */\r
     bool isAdobeAudition() const noexcept     { return type == AdobeAudition; }\r
+    /** Returns true if the host is com.apple.audio.InfoHelper. */\r
+    bool isAppleInfoHelper() const noexcept   { return type == AppleInfoHelper; }\r
     /** Returns true if the host is Ardour. */\r
     bool isArdour() const noexcept            { return type == Ardour; }\r
     /** Returns true if the host is AU Lab. */\r
     bool isAULab() const noexcept             { return type == AULab; }\r
+    /** Returns true if the host is auval. */\r
+    bool isAUVal() const noexcept             { return type == AUVal; }\r
     /** Returns true if the host is Bitwig Studio. */\r
     bool isBitwigStudio() const noexcept      { return type == BitwigStudio; }\r
     /** Returns true if the host is any version of Steinberg Cubase. */\r
index 1fad305d9a71aaf9a929590bad2961a824cf4c07..c24c52b94dea82998ed5dde0fb022d0caae159b5 100644 (file)
@@ -49,34 +49,34 @@ public:
     using ValueFromString = std::function<Value (const String&)>;\r
 \r
     /** An optional lambda function that converts a non-normalised value to a string with a maximum length. This may be used by hosts to display the parameter's value. */\r
-    JUCE_NODISCARD auto withStringFromValueFunction (StringFromValue x)                       const { return withMember (asDerived(), &Derived::stringFromValue, std::move (x)); }\r
+    [[nodiscard]] auto withStringFromValueFunction (StringFromValue x)                       const { return withMember (asDerived(), &Derived::stringFromValue, std::move (x)); }\r
 \r
     /** An optional lambda function that parses a string and converts it into a non-normalised value. Some hosts use this to allow users to type in parameter values. */\r
-    JUCE_NODISCARD auto withValueFromStringFunction (ValueFromString x)                       const { return withMember (asDerived(), &Derived::valueFromString, std::move (x)); }\r
+    [[nodiscard]] auto withValueFromStringFunction (ValueFromString x)                       const { return withMember (asDerived(), &Derived::valueFromString, std::move (x)); }\r
 \r
     /** See AudioProcessorParameterWithIDAttributes::withLabel() */\r
-    JUCE_NODISCARD auto withLabel (String x)                                                  const { return withMember (asDerived(), &Derived::attributes, attributes.withLabel (std::move (x))); }\r
+    [[nodiscard]] auto withLabel (String x)                                                  const { return withMember (asDerived(), &Derived::attributes, attributes.withLabel (std::move (x))); }\r
 \r
     /** See AudioProcessorParameterWithIDAttributes::withCategory() */\r
-    JUCE_NODISCARD auto withCategory (Category x)                                             const { return withMember (asDerived(), &Derived::attributes, attributes.withCategory (std::move (x))); }\r
+    [[nodiscard]] auto withCategory (Category x)                                             const { return withMember (asDerived(), &Derived::attributes, attributes.withCategory (std::move (x))); }\r
 \r
     /** See AudioProcessorParameter::isMetaParameter() */\r
-    JUCE_NODISCARD auto withMeta (bool x)                                                     const { return withMember (asDerived(), &Derived::attributes, attributes.withMeta (std::move (x))); }\r
+    [[nodiscard]] auto withMeta (bool x)                                                     const { return withMember (asDerived(), &Derived::attributes, attributes.withMeta (std::move (x))); }\r
 \r
     /** See AudioProcessorParameter::isAutomatable() */\r
-    JUCE_NODISCARD auto withAutomatable (bool x)                                              const { return withMember (asDerived(), &Derived::attributes, attributes.withAutomatable (std::move (x))); }\r
+    [[nodiscard]] auto withAutomatable (bool x)                                              const { return withMember (asDerived(), &Derived::attributes, attributes.withAutomatable (std::move (x))); }\r
 \r
     /** See AudioProcessorParameter::isOrientationInverted() */\r
-    JUCE_NODISCARD auto withInverted (bool x)                                                 const { return withMember (asDerived(), &Derived::attributes, attributes.withInverted (std::move (x))); }\r
+    [[nodiscard]] auto withInverted (bool x)                                                 const { return withMember (asDerived(), &Derived::attributes, attributes.withInverted (std::move (x))); }\r
 \r
     /** An optional lambda function that converts a non-normalised value to a string with a maximum length. This may be used by hosts to display the parameter's value. */\r
-    JUCE_NODISCARD const auto& getStringFromValueFunction()                                   const { return stringFromValue; }\r
+    [[nodiscard]] const auto& getStringFromValueFunction()                                   const { return stringFromValue; }\r
 \r
     /** An optional lambda function that parses a string and converts it into a non-normalised value. Some hosts use this to allow users to type in parameter values. */\r
-    JUCE_NODISCARD const auto& getValueFromStringFunction()                                   const { return valueFromString; }\r
+    [[nodiscard]] const auto& getValueFromStringFunction()                                   const { return valueFromString; }\r
 \r
     /** Gets attributes that would also apply to an AudioProcessorParameterWithID */\r
-    JUCE_NODISCARD const auto& getAudioProcessorParameterWithIDAttributes()                   const { return attributes; }\r
+    [[nodiscard]] const auto& getAudioProcessorParameterWithIDAttributes()                   const { return attributes; }\r
 \r
 private:\r
     auto& asDerived() const { return *static_cast<const Derived*> (this); }\r
diff --git a/modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp b/modules/juce_audio_processors/utilities/juce_VSTCallbackHandler.cpp
new file mode 100644 (file)
index 0000000..e8b42e9
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
+   Agreement and JUCE Privacy Policy.\r
+\r
+   End User License Agreement: www.juce.com/juce-7-licence\r
+   Privacy Policy: www.juce.com/juce-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+pointer_sized_int VSTCallbackHandler::handleVstPluginCanDo ([[maybe_unused]] int32 index,\r
+                                                            [[maybe_unused]] pointer_sized_int value,\r
+                                                            [[maybe_unused]] void* ptr,\r
+                                                            [[maybe_unused]] float opt)\r
+{\r
+    return 0;\r
+}\r
+\r
+void VSTCallbackHandler::handleVstHostCallbackAvailable ([[maybe_unused]] std::function<VstHostCallbackType>&& callback) {}\r
+\r
+} // namespace juce\r
index d5a4ea5e05ec2a97bee9c3b5874169c6c5d0bff9..9fe3a0ad82c38441769e702e275ee782d1d18ef2 100644 (file)
@@ -46,11 +46,7 @@ struct VSTCallbackHandler
     virtual pointer_sized_int handleVstPluginCanDo (int32 index,\r
                                                     pointer_sized_int value,\r
                                                     void* ptr,\r
-                                                    float opt)\r
-    {\r
-        ignoreUnused (index, value, ptr, opt);\r
-        return 0;\r
-    }\r
+                                                    float opt);\r
 \r
     /** This is called by the VST plug-in wrapper when it receives unhandled\r
         vendor specific calls from the host.\r
@@ -71,10 +67,7 @@ struct VSTCallbackHandler
     /** This is called once by the VST plug-in wrapper after its constructor.\r
         You can use the supplied function to query the VST host.\r
     */\r
-    virtual void handleVstHostCallbackAvailable (std::function<VstHostCallbackType>&& callback)\r
-    {\r
-        ignoreUnused (callback);\r
-    }\r
+    virtual void handleVstHostCallbackAvailable (std::function<VstHostCallbackType>&& callback);\r
 };\r
 \r
 } // namespace juce\r
index d616a33b47ff1e59f9e6bea1d5f4da5530fa3c22..8f2277cf1757f68c63867f778642c926d76d86f4 100644 (file)
@@ -68,7 +68,7 @@ public:
     ~AudioCDReader() override;\r
 \r
     /** Implementation of the AudioFormatReader method. */\r
-    bool readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+    bool readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                       int64 startSampleInFile, int numSamples) override;\r
 \r
     /** Checks whether the CD has been removed from the drive. */\r
index 3ffc44384f54112e1a66b3aefea05682c6437490..809162f583fb859abcd0e49c526115611e728d59 100644 (file)
@@ -1193,11 +1193,18 @@ void AudioDeviceSelectorComponent::updateAllControls()
 \r
 void AudioDeviceSelectorComponent::handleBluetoothButton()\r
 {\r
-    if (! RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi))\r
-        RuntimePermissions::request (RuntimePermissions::bluetoothMidi, nullptr);\r
-\r
     if (RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi))\r
+    {\r
         BluetoothMidiDevicePairingDialogue::open();\r
+    }\r
+    else\r
+    {\r
+        RuntimePermissions::request (RuntimePermissions::bluetoothMidi, [] (auto)\r
+        {\r
+            if (RuntimePermissions::isGranted (RuntimePermissions::bluetoothMidi))\r
+                BluetoothMidiDevicePairingDialogue::open();\r
+        });\r
+    }\r
 }\r
 \r
 ListBox* AudioDeviceSelectorComponent::getMidiInputSelectorListBox() const noexcept\r
index 4f0e5a2d1deffb222787b34c5c7403b5097f6dca..377b70edcd6468566d102c4ab5366fc314de72f6 100644 (file)
@@ -83,6 +83,66 @@ private:
     int8 values[2];\r
 };\r
 \r
+\r
+//==============================================================================\r
+template <typename T>\r
+class AudioBufferReader  : public AudioFormatReader\r
+{\r
+public:\r
+    AudioBufferReader (const AudioBuffer<T>* bufferIn, double rate)\r
+        : AudioFormatReader (nullptr, "AudioBuffer"), buffer (bufferIn)\r
+    {\r
+        sampleRate = rate;\r
+        bitsPerSample = 32;\r
+        lengthInSamples = buffer->getNumSamples();\r
+        numChannels = (unsigned int) buffer->getNumChannels();\r
+        usesFloatingPointData = std::is_floating_point_v<T>;\r
+    }\r
+\r
+    bool readSamples (int* const* destChannels,\r
+                      int numDestChannels,\r
+                      int startOffsetInDestBuffer,\r
+                      int64 startSampleInFile,\r
+                      int numSamples) override\r
+    {\r
+        clearSamplesBeyondAvailableLength (destChannels, numDestChannels, startOffsetInDestBuffer,\r
+                                           startSampleInFile, numSamples, lengthInSamples);\r
+\r
+        const auto numAvailableSamples = (int) ((int64) buffer->getNumSamples() - startSampleInFile);\r
+        const auto numSamplesToCopy = std::clamp (numAvailableSamples, 0, numSamples);\r
+\r
+        if (numSamplesToCopy == 0)\r
+            return true;\r
+\r
+        for (int i = 0; i < numDestChannels; ++i)\r
+        {\r
+            if (void* targetChannel = destChannels[i])\r
+            {\r
+                const auto dest = DestType (targetChannel) + startOffsetInDestBuffer;\r
+\r
+                if (i < buffer->getNumChannels())\r
+                    dest.convertSamples (SourceType (buffer->getReadPointer (i) + startSampleInFile), numSamplesToCopy);\r
+                else\r
+                    dest.clearSamples (numSamples);\r
+            }\r
+        }\r
+\r
+        return true;\r
+    }\r
+\r
+private:\r
+    using SourceNumericalType =\r
+        std::conditional_t<std::is_same_v<T, int>, AudioData::Int32,\r
+                           std::conditional_t<std::is_same_v<T, float>, AudioData::Float32, void>>;\r
+\r
+    using DestinationNumericalType = std::conditional_t<std::is_floating_point_v<T>, AudioData::Float32, AudioData::Int32>;\r
+\r
+    using DestType   = AudioData::Pointer<DestinationNumericalType, AudioData::LittleEndian, AudioData::NonInterleaved, AudioData::NonConst>;\r
+    using SourceType = AudioData::Pointer<SourceNumericalType,      AudioData::LittleEndian, AudioData::NonInterleaved, AudioData::Const>;\r
+\r
+    const AudioBuffer<T>* buffer;\r
+};\r
+\r
 //==============================================================================\r
 class AudioThumbnail::LevelDataSource   : public TimeSliceClient\r
 {\r
@@ -687,6 +747,16 @@ void AudioThumbnail::setReader (AudioFormatReader* newReader, int64 hash)
         setDataSource (new LevelDataSource (*this, newReader, hash));\r
 }\r
 \r
+void AudioThumbnail::setSource (const AudioBuffer<float>* newSource, double rate, int64 hash)\r
+{\r
+    setReader (new AudioBufferReader<float> (newSource, rate), hash);\r
+}\r
+\r
+void AudioThumbnail::setSource (const AudioBuffer<int>* newSource, double rate, int64 hash)\r
+{\r
+    setReader (new AudioBufferReader<int> (newSource, rate), hash);\r
+}\r
+\r
 int64 AudioThumbnail::getHashCode() const\r
 {\r
     return source == nullptr ? 0 : source->hashCode;\r
index ca912c892405823aefc06b5a42874f5bf7da3732..156aeaa09a16ca5f98bea8fae33c01e2a1dc049d 100644 (file)
@@ -99,6 +99,18 @@ public:
     */\r
     void setReader (AudioFormatReader* newReader, int64 hashCode) override;\r
 \r
+    /** Sets an AudioBuffer as the source for the thumbnail.\r
+\r
+        The buffer contents aren't copied and you must ensure that the lifetime of the buffer is\r
+        valid for as long as the AudioThumbnail uses it as its source. Calling this function will\r
+        start reading the audio in a background thread (unless the hash code can be looked-up\r
+        successfully in the thumbnail cache).\r
+    */\r
+    void setSource (const AudioBuffer<float>* newSource, double sampleRate, int64 hashCode);\r
+\r
+    /** Same as the other setSource() overload except for int data. */\r
+    void setSource (const AudioBuffer<int>* newSource, double sampleRate, int64 hashCode);\r
+\r
     /** Resets the thumbnail, ready for adding data with the specified format.\r
         If you're going to generate a thumbnail yourself, call this before using addBlock()\r
         to add the data.\r
index 4900cc4876047d222b319a05b6605250941fa556..59800c31c97ec58fba909229f3cf162967f16a28 100644 (file)
@@ -64,7 +64,7 @@ AudioThumbnailCache::AudioThumbnailCache (const int maxNumThumbs)
       maxNumThumbsToStore (maxNumThumbs)\r
 {\r
     jassert (maxNumThumbsToStore > 0);\r
-    thread.startThread (2);\r
+    thread.startThread (Thread::Priority::low);\r
 }\r
 \r
 AudioThumbnailCache::~AudioThumbnailCache()\r
index fe12591f8b55684ae2f9d3e713325bc189b1ffb9..765c7a86c86d2254d3b70cb0646a4766d4fc7e7f 100644 (file)
@@ -119,7 +119,7 @@ void AudioVisualiserComponent::clear()
         c->clear();\r
 }\r
 \r
-void AudioVisualiserComponent::pushBuffer (const float** d, int numChannels, int num)\r
+void AudioVisualiserComponent::pushBuffer (const float* const* d, int numChannels, int num)\r
 {\r
     numChannels = jmin (numChannels, channels.size());\r
 \r
index 28cd33fe2c741998300534b217c606731b224e9f..b1ba56c6bc9a6b74d2b346dfcf04dc3399a7ab93 100644 (file)
@@ -87,7 +87,7 @@ public:
         The number of channels provided here is expected to match the number of channels\r
         that this AudioVisualiserComponent has been told to use.\r
     */\r
-    void pushBuffer (const float** channelData, int numChannels, int numSamples);\r
+    void pushBuffer (const float* const* channelData, int numChannels, int numSamples);\r
 \r
     /** Pushes a single sample (per channel).\r
         The number of channels provided here is expected to match the number of channels\r
index e070fcdbf1e7b73f7bcc7b3eac3b6821e1a76b06..b149bd6bb11e44f903cf5e82ee1409f2862fed0b 100644 (file)
@@ -57,13 +57,13 @@ public:
 \r
     //==============================================================================\r
     /** Sets the note-on velocity, or "strike", value that will be used when triggering new notes. */\r
-    void setVelocity (float newVelocity)                                 { velocity = jlimit (newVelocity, 0.0f, 1.0f); }\r
+    void setVelocity (float newVelocity)                                 { velocity = jlimit (0.0f, 1.0f, newVelocity); }\r
 \r
     /** Sets the pressure value that will be used for new notes. */\r
-    void setPressure (float newPressure)                                 { pressure = jlimit (newPressure, 0.0f, 1.0f); }\r
+    void setPressure (float newPressure)                                 { pressure = jlimit (0.0f, 1.0f, newPressure); }\r
 \r
     /** Sets the note-off velocity, or "lift", value that will be used when notes are released. */\r
-    void setLift (float newLift)                                         { lift = jlimit (newLift, 0.0f, 1.0f); }\r
+    void setLift (float newLift)                                         { lift = jlimit (0.0f, 1.0f, newLift); }\r
 \r
     /** Use this to enable the mouse source pressure to be used for the initial note-on\r
         velocity, or "strike", value if the mouse source supports it.\r
index be3ff67d0d1e9a307ad7aa849a05d6a875933639..fbd90eac384cc2900cdaf402652d46c0521394ba 100644 (file)
@@ -478,4 +478,9 @@ void MidiKeyboardComponent::handleNoteOff (MidiKeyboardState*, int /*midiChannel
     noPendingUpdates.store (false);\r
 }\r
 \r
+//==============================================================================\r
+bool MidiKeyboardComponent::mouseDownOnKey    ([[maybe_unused]] int midiNoteNumber, [[maybe_unused]] const MouseEvent& e)  { return true; }\r
+bool MidiKeyboardComponent::mouseDraggedToKey ([[maybe_unused]] int midiNoteNumber, [[maybe_unused]] const MouseEvent& e)  { return true; }\r
+void MidiKeyboardComponent::mouseUpOnKey      ([[maybe_unused]] int midiNoteNumber, [[maybe_unused]] const MouseEvent& e)  {}\r
+\r
 } // namespace juce\r
index 70dedb688d33bfa619e7264dd4c5245b3fbe5a34..2c9c6ab6c2fbb9da16bf2bd4e3d1c98dd1eeffa8 100644 (file)
@@ -193,7 +193,7 @@ public:
 \r
         @see mouseDraggedToKey\r
     */\r
-    virtual bool mouseDownOnKey (int midiNoteNumber, const MouseEvent& e)     { ignoreUnused (midiNoteNumber, e); return true; }\r
+    virtual bool mouseDownOnKey (int midiNoteNumber, const MouseEvent& e);\r
 \r
     /** Callback when the mouse is dragged from one key onto another.\r
 \r
@@ -202,13 +202,13 @@ public:
 \r
         @see mouseDownOnKey\r
     */\r
-    virtual bool mouseDraggedToKey (int midiNoteNumber, const MouseEvent& e)  { ignoreUnused (midiNoteNumber, e); return true; }\r
+    virtual bool mouseDraggedToKey (int midiNoteNumber, const MouseEvent& e);\r
 \r
     /** Callback when the mouse is released from a key.\r
 \r
         @see mouseDownOnKey\r
     */\r
-    virtual void mouseUpOnKey (int midiNoteNumber, const MouseEvent& e)       { ignoreUnused (midiNoteNumber, e); }\r
+    virtual void mouseUpOnKey (int midiNoteNumber, const MouseEvent& e);\r
 \r
     /** Allows text to be drawn on the white notes.\r
 \r
index 6d0c1a72dced0692e3f4923b07d9441709e6b4c3..c7170cdb1b00464355419dd8aca7a65cd6c03990 100644 (file)
 \r
   ID:                 juce_audio_utils\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE extra audio utility classes\r
   description:        Classes for audio-related GUI and miscellaneous tasks.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_audio_processors, juce_audio_formats, juce_audio_devices\r
   OSXFrameworks:      CoreAudioKit DiscRecording\r
index a653858d80c146a23217fbc2c8aed310f97f9c8d..739b81bb4d78e54121e0fbf8faea2c5446dc5907 100644 (file)
@@ -50,7 +50,7 @@ void AudioCDReader::refreshTrackLengths()
 {\r
 }\r
 \r
-bool AudioCDReader::readSamples (int**, int, int,\r
+bool AudioCDReader::readSamples (int* const*, int, int,\r
                                  int64, int)\r
 {\r
     return false;\r
index 9b5ee4e64462d8afd46a1afe96a5710c380fc7e9..9eb0d6e0611bd8569f185d19cb8f34a8950933c0 100644 (file)
@@ -171,14 +171,13 @@ void AudioCDReader::refreshTrackLengths()
     if (toc.exists())\r
     {\r
         XmlDocument doc (toc);\r
-        const char* error = CDReaderHelpers::getTrackOffsets (doc, trackStartSamples);\r
-        ignoreUnused (error); // could be logged..\r
+        [[maybe_unused]] const char* error = CDReaderHelpers::getTrackOffsets (doc, trackStartSamples);\r
 \r
         lengthInSamples = trackStartSamples.getLast() - trackStartSamples.getFirst();\r
     }\r
 }\r
 \r
-bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool AudioCDReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                                  int64 startSampleInFile, int numSamples)\r
 {\r
     while (numSamples > 0)\r
index f1e00439e0688190d18f2dd945997434d5610295..69fb26f50c125f7304cdab2cd3e76bb6dc39470b 100644 (file)
@@ -1035,7 +1035,7 @@ AudioCDReader::~AudioCDReader()
     delete device;\r
 }\r
 \r
-bool AudioCDReader::readSamples (int** destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
+bool AudioCDReader::readSamples (int* const* destSamples, int numDestChannels, int startOffsetInDestBuffer,\r
                                  int64 startSampleInFile, int numSamples)\r
 {\r
     using namespace CDReaderHelpers;\r
index bb1c5580fa6cbd88c3378f880f48b50b2cff96f2..58d64eba148c364f8780325acd421e30a93787d6 100644 (file)
@@ -30,10 +30,10 @@ template <typename Value>
 struct ChannelInfo\r
 {\r
     ChannelInfo() = default;\r
-    ChannelInfo (Value** dataIn, int numChannelsIn)\r
+    ChannelInfo (Value* const* dataIn, int numChannelsIn)\r
         : data (dataIn), numChannels (numChannelsIn)  {}\r
 \r
-    Value** data = nullptr;\r
+    Value* const* data = nullptr;\r
     int numChannels = 0;\r
 };\r
 \r
@@ -98,7 +98,7 @@ static void initialiseIoBuffers (ChannelInfo<const float> ins,
 \r
         for (auto i = processorOuts; i < processorIns; ++i)\r
         {\r
-            channels[totalNumChans] = tempBuffer.getWritePointer (i - outs.numChannels);\r
+            channels[totalNumChans] = tempBuffer.getWritePointer (i - processorOuts);\r
             prepareInputChannel (i);\r
             ++totalNumChans;\r
         }\r
@@ -235,9 +235,9 @@ void AudioProcessorPlayer::setMidiOutput (MidiOutput* midiOutputToUse)
 }\r
 \r
 //==============================================================================\r
-void AudioProcessorPlayer::audioDeviceIOCallbackWithContext (const float** const inputChannelData,\r
+void AudioProcessorPlayer::audioDeviceIOCallbackWithContext (const float* const* const inputChannelData,\r
                                                              const int numInputChannels,\r
-                                                             float** const outputChannelData,\r
+                                                             float* const* const outputChannelData,\r
                                                              const int numOutputChannels,\r
                                                              const int numSamples,\r
                                                              const AudioIODeviceCallbackContext& context)\r
@@ -281,12 +281,14 @@ void AudioProcessorPlayer::audioDeviceIOCallbackWithContext (const float** const
                   sampleCount (sampleCountIn),\r
                   seconds ((double) sampleCountIn / sampleRateIn)\r
             {\r
-                processor.setPlayHead (this);\r
+                if (useThisPlayhead)\r
+                    processor.setPlayHead (this);\r
             }\r
 \r
             ~PlayHead() override\r
             {\r
-                processor.setPlayHead (nullptr);\r
+                if (useThisPlayhead)\r
+                    processor.setPlayHead (nullptr);\r
             }\r
 \r
         private:\r
@@ -303,6 +305,7 @@ void AudioProcessorPlayer::audioDeviceIOCallbackWithContext (const float** const
             Optional<uint64_t> hostTimeNs;\r
             uint64_t sampleCount;\r
             double seconds;\r
+            bool useThisPlayhead = processor.getPlayHead() == nullptr;\r
         };\r
 \r
         PlayHead playHead { *processor,\r
index 8f14d52e9564f93662c2fbe72ba9e6729358cdd9..9ba98ba95895a4f57c7d08bc657c412237128257 100644 (file)
@@ -92,7 +92,7 @@ public:
 \r
     //==============================================================================\r
     /** @internal */\r
-    void audioDeviceIOCallbackWithContext (const float**, int, float**, int, int, const AudioIODeviceCallbackContext&) override;\r
+    void audioDeviceIOCallbackWithContext (const float* const*, int, float* const*, int, int, const AudioIODeviceCallbackContext&) override;\r
     /** @internal */\r
     void audioDeviceAboutToStart (AudioIODevice*) override;\r
     /** @internal */\r
index 3426fa3beb5d05a4f64607e799b668a8ad56efb7..90abda880fdc2c291d68f0d8fdefc27c27d4a457 100644 (file)
@@ -242,15 +242,16 @@ void SoundPlayer::playTestSound()
 }\r
 \r
 //==============================================================================\r
-void SoundPlayer::audioDeviceIOCallback (const float** inputChannelData,\r
-                                         int numInputChannels,\r
-                                         float** outputChannelData,\r
-                                         int numOutputChannels,\r
-                                         int numSamples)\r
+void SoundPlayer::audioDeviceIOCallbackWithContext (const float* const* inputChannelData,\r
+                                                    int numInputChannels,\r
+                                                    float* const* outputChannelData,\r
+                                                    int numOutputChannels,\r
+                                                    int numSamples,\r
+                                                    const AudioIODeviceCallbackContext& context)\r
 {\r
-    player.audioDeviceIOCallback (inputChannelData, numInputChannels,\r
-                                  outputChannelData, numOutputChannels,\r
-                                  numSamples);\r
+    player.audioDeviceIOCallbackWithContext (inputChannelData, numInputChannels,\r
+                                             outputChannelData, numOutputChannels,\r
+                                             numSamples, context);\r
 }\r
 \r
 void SoundPlayer::audioDeviceAboutToStart (AudioIODevice* device)\r
index e4c36aca344e9e069125e52621da6c504ec6b523..07edc7d308bea8d113afb679911aba3c445954e9 100644 (file)
@@ -110,7 +110,7 @@ public:
 \r
     //==============================================================================\r
     /** @internal */\r
-    void audioDeviceIOCallback (const float**, int, float**, int, int) override;\r
+    void audioDeviceIOCallbackWithContext (const float* const*, int, float* const*, int, int, const AudioIODeviceCallbackContext&) override;\r
     /** @internal */\r
     void audioDeviceAboutToStart (AudioIODevice*) override;\r
     /** @internal */\r
index cf952719367c9c8667840644ab84658a210044d6..64593859ae2bb177911d15ec93cdb272a816ddee 100644 (file)
 \r
   ID:                 juce_box2d\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE wrapper for the Box2D physics engine\r
   description:        The Box2D physics engine and some utility classes.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_graphics\r
 \r
index 05f9579974fbc1bbe433ef28616f6b68d8924c63..316e54526f9fae3b5218938f7251e8db1186219f 100644 (file)
@@ -649,7 +649,7 @@ public:
         @see add\r
     */\r
     template <class OtherArrayType>\r
-    typename std::enable_if<! std::is_pointer<OtherArrayType>::value, void>::type\r
+    std::enable_if_t<! std::is_pointer_v<OtherArrayType>, void>\r
     addArray (const OtherArrayType& arrayToAddFrom,\r
               int startIndex,\r
               int numElementsToAdd = -1)\r
@@ -727,32 +727,7 @@ public:
         @see addSorted, sort\r
     */\r
     template <typename ElementComparator, typename TargetValueType>\r
-    int indexOfSorted (ElementComparator& comparator, TargetValueType elementToLookFor) const\r
-    {\r
-        ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this\r
-                                   // avoids getting warning messages about the parameter being unused\r
-\r
-        const ScopedLockType lock (getLock());\r
-\r
-        for (int s = 0, e = values.size();;)\r
-        {\r
-            if (s >= e)\r
-                return -1;\r
-\r
-            if (comparator.compareElements (elementToLookFor, values[s]) == 0)\r
-                return s;\r
-\r
-            auto halfway = (s + e) / 2;\r
-\r
-            if (halfway == s)\r
-                return -1;\r
-\r
-            if (comparator.compareElements (elementToLookFor, values[halfway]) >= 0)\r
-                s = halfway;\r
-            else\r
-                e = halfway;\r
-        }\r
-    }\r
+    int indexOfSorted (ElementComparator& comparator, TargetValueType elementToLookFor) const;\r
 \r
     //==============================================================================\r
     /** Removes an element from the array.\r
@@ -1106,14 +1081,7 @@ public:
         @see addSorted, indexOfSorted, sortArray\r
     */\r
     template <class ElementComparator>\r
-    void sort (ElementComparator& comparator,\r
-               bool retainOrderOfEquivalentItems = false)\r
-    {\r
-        const ScopedLockType lock (getLock());\r
-        ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this\r
-                                   // avoids getting warning messages about the parameter being unused\r
-        sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);\r
-    }\r
+    void sort (ElementComparator& comparator, bool retainOrderOfEquivalentItems = false);\r
 \r
     //==============================================================================\r
     /** Returns the CriticalSection that locks this array.\r
@@ -1150,4 +1118,43 @@ private:
     }\r
 };\r
 \r
+//==============================================================================\r
+template <typename ElementType, typename TypeOfCriticalSectionToUse, int minimumAllocatedSize>\r
+template <typename ElementComparator, typename TargetValueType>\r
+int Array<ElementType, TypeOfCriticalSectionToUse, minimumAllocatedSize>::indexOfSorted (\r
+    [[maybe_unused]] ElementComparator& comparator,\r
+    TargetValueType elementToLookFor) const\r
+{\r
+    const ScopedLockType lock (getLock());\r
+\r
+    for (int s = 0, e = values.size();;)\r
+    {\r
+        if (s >= e)\r
+            return -1;\r
+\r
+        if (comparator.compareElements (elementToLookFor, values[s]) == 0)\r
+            return s;\r
+\r
+        auto halfway = (s + e) / 2;\r
+\r
+        if (halfway == s)\r
+            return -1;\r
+\r
+        if (comparator.compareElements (elementToLookFor, values[halfway]) >= 0)\r
+            s = halfway;\r
+        else\r
+            e = halfway;\r
+    }\r
+}\r
+\r
+template <typename ElementType, typename TypeOfCriticalSectionToUse, int minimumAllocatedSize>\r
+template <class ElementComparator>\r
+void Array<ElementType, TypeOfCriticalSectionToUse, minimumAllocatedSize>::sort (\r
+    [[maybe_unused]] ElementComparator& comparator,\r
+    bool retainOrderOfEquivalentItems)\r
+{\r
+    const ScopedLockType lock (getLock());\r
+    sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);\r
+}\r
+\r
 } // namespace juce\r
index 1553e05b16e9407f1172009f6179db95f3394b6a..9d2657c391343666489cef966a6163e2d3faca85 100644 (file)
@@ -105,9 +105,9 @@ class ArrayBaseTests  : public UnitTest
     using NoncopyableType = ArrayBaseTestsHelpers::NonTriviallyCopyableType;\r
 \r
    #if ! (defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__))\r
-    static_assert (std::is_trivially_copyable<CopyableType>::value,\r
+    static_assert (std::is_trivially_copyable_v<CopyableType>,\r
                    "Test TriviallyCopyableType is not trivially copyable");\r
-    static_assert (! std::is_trivially_copyable<NoncopyableType>::value,\r
+    static_assert (! std::is_trivially_copyable_v<NoncopyableType>,\r
                    "Test NonTriviallyCopyableType is trivially copyable");\r
    #endif\r
 \r
index 515bf0f24031c9ccdc5e4bf9e140ed2f359fbeac..353fcfae50a571b1ab045a727c5a71e751186048 100644 (file)
@@ -43,8 +43,8 @@ private:
     using ParameterType = typename TypeHelpers::ParameterType<ElementType>::type;\r
 \r
     template <class OtherElementType, class OtherCriticalSection>\r
-    using AllowConversion = typename std::enable_if<! std::is_same<std::tuple<ElementType, TypeOfCriticalSectionToUse>,\r
-                                                                   std::tuple<OtherElementType, OtherCriticalSection>>::value>::type;\r
+    using AllowConversion = std::enable_if_t<! std::is_same_v<std::tuple<ElementType, TypeOfCriticalSectionToUse>,\r
+                                                              std::tuple<OtherElementType, OtherCriticalSection>>>;\r
 \r
 public:\r
     //==============================================================================\r
@@ -304,7 +304,7 @@ public:
     }\r
 \r
     template <class OtherArrayType>\r
-    typename std::enable_if<! std::is_pointer<OtherArrayType>::value, int>::type\r
+    std::enable_if_t<! std::is_pointer_v<OtherArrayType>, int>\r
     addArray (const OtherArrayType& arrayToAddFrom,\r
               int startIndex, int numElementsToAdd = -1)\r
     {\r
@@ -385,64 +385,49 @@ public:
 \r
 private:\r
     //==============================================================================\r
-    template <typename T>\r
    #if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)\r
-    using IsTriviallyCopyable = std::is_scalar<T>;\r
+    static constexpr auto isTriviallyCopyable = std::is_scalar_v<ElementType>;\r
    #else\r
-    using IsTriviallyCopyable = std::is_trivially_copyable<T>;\r
+    static constexpr auto isTriviallyCopyable = std::is_trivially_copyable_v<ElementType>;\r
    #endif\r
 \r
-    template <typename T>\r
-    using TriviallyCopyableVoid = typename std::enable_if<IsTriviallyCopyable<T>::value, void>::type;\r
-\r
-    template <typename T>\r
-    using NonTriviallyCopyableVoid = typename std::enable_if<! IsTriviallyCopyable<T>::value, void>::type;\r
-\r
     //==============================================================================\r
-    template <typename T = ElementType>\r
-    TriviallyCopyableVoid<T> addArrayInternal (const ElementType* otherElements, int numElements)\r
-    {\r
-        if (numElements > 0)\r
-            memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType));\r
-    }\r
-\r
-    template <typename Type, typename T = ElementType>\r
-    TriviallyCopyableVoid<T> addArrayInternal (const Type* otherElements, int numElements)\r
-    {\r
-        auto* start = elements + numUsed;\r
-\r
-        while (--numElements >= 0)\r
-            new (start++) ElementType (*(otherElements++));\r
-    }\r
-\r
-    template <typename Type, typename T = ElementType>\r
-    NonTriviallyCopyableVoid<T> addArrayInternal (const Type* otherElements, int numElements)\r
+    template <typename Type>\r
+    void addArrayInternal (const Type* otherElements, int numElements)\r
     {\r
-        auto* start = elements + numUsed;\r
+        if constexpr (isTriviallyCopyable && std::is_same_v<Type, ElementType>)\r
+        {\r
+            if (numElements > 0)\r
+                memcpy (elements + numUsed, otherElements, (size_t) numElements * sizeof (ElementType));\r
+        }\r
+        else\r
+        {\r
+            auto* start = elements + numUsed;\r
 \r
-        while (--numElements >= 0)\r
-            new (start++) ElementType (*(otherElements++));\r
+            while (--numElements >= 0)\r
+                new (start++) ElementType (*(otherElements++));\r
+        }\r
     }\r
 \r
     //==============================================================================\r
-    template <typename T = ElementType>\r
-    TriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements)\r
+    void setAllocatedSizeInternal (int numElements)\r
     {\r
-        elements.realloc ((size_t) numElements);\r
-    }\r
-\r
-    template <typename T = ElementType>\r
-    NonTriviallyCopyableVoid<T> setAllocatedSizeInternal (int numElements)\r
-    {\r
-        HeapBlock<ElementType> newElements (numElements);\r
-\r
-        for (int i = 0; i < numUsed; ++i)\r
+        if constexpr (isTriviallyCopyable)\r
         {\r
-            new (newElements + i) ElementType (std::move (elements[i]));\r
-            elements[i].~ElementType();\r
+            elements.realloc ((size_t) numElements);\r
         }\r
+        else\r
+        {\r
+            HeapBlock<ElementType> newElements (numElements);\r
+\r
+            for (int i = 0; i < numUsed; ++i)\r
+            {\r
+                new (newElements + i) ElementType (std::move (elements[i]));\r
+                elements[i].~ElementType();\r
+            }\r
 \r
-        elements = std::move (newElements);\r
+            elements = std::move (newElements);\r
+        }\r
     }\r
 \r
     //==============================================================================\r
@@ -458,106 +443,106 @@ private:
         return elements + indexToInsertAt;\r
     }\r
 \r
-    template <typename T = ElementType>\r
-    TriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements)\r
-    {\r
-        auto* start = elements + indexToInsertAt;\r
-        auto numElementsToShift = numUsed - indexToInsertAt;\r
-        memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType));\r
-    }\r
-\r
-    template <typename T = ElementType>\r
-    NonTriviallyCopyableVoid<T> createInsertSpaceInternal (int indexToInsertAt, int numElements)\r
+    void createInsertSpaceInternal (int indexToInsertAt, int numElements)\r
     {\r
-        auto* end = elements + numUsed;\r
-        auto* newEnd = end + numElements;\r
-        auto numElementsToShift = numUsed - indexToInsertAt;\r
-\r
-        for (int i = 0; i < numElementsToShift; ++i)\r
+        if constexpr (isTriviallyCopyable)\r
         {\r
-            new (--newEnd) ElementType (std::move (*(--end)));\r
-            end->~ElementType();\r
+            auto* start = elements + indexToInsertAt;\r
+            auto numElementsToShift = numUsed - indexToInsertAt;\r
+            memmove (start + numElements, start, (size_t) numElementsToShift * sizeof (ElementType));\r
         }\r
-    }\r
-\r
-    //==============================================================================\r
-    template <typename T = ElementType>\r
-    TriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)\r
-    {\r
-        auto* start = elements + indexToRemoveAt;\r
-        auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);\r
-        memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType));\r
-    }\r
-\r
-    template <typename T = ElementType>\r
-    NonTriviallyCopyableVoid<T> removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)\r
-    {\r
-        auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);\r
-        auto* destination = elements + indexToRemoveAt;\r
-        auto* source = destination + numElementsToRemove;\r
-\r
-        for (int i = 0; i < numElementsToShift; ++i)\r
-            moveAssignElement (destination++, std::move (*(source++)));\r
+        else\r
+        {\r
+            auto* end = elements + numUsed;\r
+            auto* newEnd = end + numElements;\r
+            auto numElementsToShift = numUsed - indexToInsertAt;\r
 \r
-        for (int i = 0; i < numElementsToRemove; ++i)\r
-            (destination++)->~ElementType();\r
+            for (int i = 0; i < numElementsToShift; ++i)\r
+            {\r
+                new (--newEnd) ElementType (std::move (*(--end)));\r
+                end->~ElementType();\r
+            }\r
+        }\r
     }\r
 \r
     //==============================================================================\r
-    template <typename T = ElementType>\r
-    TriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept\r
+    void removeElementsInternal (int indexToRemoveAt, int numElementsToRemove)\r
     {\r
-        char tempCopy[sizeof (ElementType)];\r
-        memcpy (tempCopy, elements + currentIndex, sizeof (ElementType));\r
-\r
-        if (newIndex > currentIndex)\r
+        if constexpr (isTriviallyCopyable)\r
         {\r
-            memmove (elements + currentIndex,\r
-                     elements + currentIndex + 1,\r
-                     (size_t) (newIndex - currentIndex) * sizeof (ElementType));\r
+            auto* start = elements + indexToRemoveAt;\r
+            auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);\r
+            memmove (start, start + numElementsToRemove, (size_t) numElementsToShift * sizeof (ElementType));\r
         }\r
         else\r
         {\r
-            memmove (elements + newIndex + 1,\r
-                     elements + newIndex,\r
-                     (size_t) (currentIndex - newIndex) * sizeof (ElementType));\r
-        }\r
+            auto numElementsToShift = numUsed - (indexToRemoveAt + numElementsToRemove);\r
+            auto* destination = elements + indexToRemoveAt;\r
+            auto* source = destination + numElementsToRemove;\r
 \r
-        memcpy (elements + newIndex, tempCopy, sizeof (ElementType));\r
+            for (int i = 0; i < numElementsToShift; ++i)\r
+                moveAssignElement (destination++, std::move (*(source++)));\r
+\r
+            for (int i = 0; i < numElementsToRemove; ++i)\r
+                (destination++)->~ElementType();\r
+        }\r
     }\r
 \r
-    template <typename T = ElementType>\r
-    NonTriviallyCopyableVoid<T> moveInternal (int currentIndex, int newIndex) noexcept\r
+    //==============================================================================\r
+    void moveInternal (int currentIndex, int newIndex) noexcept\r
     {\r
-        auto* e = elements + currentIndex;\r
-        ElementType tempCopy (std::move (*e));\r
-        auto delta = newIndex - currentIndex;\r
-\r
-        if (delta > 0)\r
+        if constexpr (isTriviallyCopyable)\r
         {\r
-            for (int i = 0; i < delta; ++i)\r
+            char tempCopy[sizeof (ElementType)];\r
+            memcpy (tempCopy, elements + currentIndex, sizeof (ElementType));\r
+\r
+            if (newIndex > currentIndex)\r
             {\r
-                moveAssignElement (e, std::move (*(e + 1)));\r
-                ++e;\r
+                memmove (elements + currentIndex,\r
+                         elements + currentIndex + 1,\r
+                         (size_t) (newIndex - currentIndex) * sizeof (ElementType));\r
             }\r
+            else\r
+            {\r
+                memmove (elements + newIndex + 1,\r
+                         elements + newIndex,\r
+                         (size_t) (currentIndex - newIndex) * sizeof (ElementType));\r
+            }\r
+\r
+            memcpy (elements + newIndex, tempCopy, sizeof (ElementType));\r
         }\r
         else\r
         {\r
-            for (int i = 0; i < -delta; ++i)\r
+            auto* e = elements + currentIndex;\r
+            ElementType tempCopy (std::move (*e));\r
+            auto delta = newIndex - currentIndex;\r
+\r
+            if (delta > 0)\r
             {\r
-                moveAssignElement (e, std::move (*(e - 1)));\r
-                --e;\r
+                for (int i = 0; i < delta; ++i)\r
+                {\r
+                    moveAssignElement (e, std::move (*(e + 1)));\r
+                    ++e;\r
+                }\r
+            }\r
+            else\r
+            {\r
+                for (int i = 0; i < -delta; ++i)\r
+                {\r
+                    moveAssignElement (e, std::move (*(e - 1)));\r
+                    --e;\r
+                }\r
             }\r
-        }\r
 \r
-        moveAssignElement (e, std::move (tempCopy));\r
+            moveAssignElement (e, std::move (tempCopy));\r
+        }\r
     }\r
 \r
     //==============================================================================\r
     template <typename... Elements>\r
     void addImpl (Elements&&... toAdd)\r
     {\r
-        ignoreUnused (std::initializer_list<int> { (((void) checkSourceIsNotAMember (toAdd)), 0)... });\r
+        (checkSourceIsNotAMember (toAdd), ...);\r
         ensureAllocatedSize (numUsed + (int) sizeof... (toAdd));\r
         addAssumingCapacityIsReady (std::forward<Elements> (toAdd)...);\r
     }\r
@@ -565,23 +550,21 @@ private:
     template <typename... Elements>\r
     void addAssumingCapacityIsReady (Elements&&... toAdd)\r
     {\r
-        ignoreUnused (std::initializer_list<int> { ((void) (new (elements + numUsed++) ElementType (std::forward<Elements> (toAdd))), 0)... });\r
+        (new (elements + numUsed++) ElementType (std::forward<Elements> (toAdd)), ...);\r
     }\r
 \r
     //==============================================================================\r
-    template <typename T = ElementType>\r
-    typename std::enable_if<std::is_move_assignable<T>::value, void>::type\r
-    moveAssignElement (ElementType* destination, ElementType&& source)\r
+    void moveAssignElement (ElementType* destination, ElementType&& source)\r
     {\r
-        *destination = std::move (source);\r
-    }\r
-\r
-    template <typename T = ElementType>\r
-    typename std::enable_if<! std::is_move_assignable<T>::value, void>::type\r
-    moveAssignElement (ElementType* destination, ElementType&& source)\r
-    {\r
-        destination->~ElementType();\r
-        new (destination) ElementType (std::move (source));\r
+        if constexpr (std::is_move_assignable_v<ElementType>)\r
+        {\r
+            *destination = std::move (source);\r
+        }\r
+        else\r
+        {\r
+            destination->~ElementType();\r
+            new (destination) ElementType (std::move (source));\r
+        }\r
     }\r
 \r
     void checkSourceIsNotAMember (const ElementType& element)\r
index 5bf7d5e12ff4cae4a0aa67e25b3df1042057c594..8f7ce2bbecfd9d461ebc83fd12c8bc181fb50652 100644 (file)
@@ -123,7 +123,7 @@ static void sortArray (ElementComparator& comparator,
     @param lastElement      the index of the last element in the range (this is non-inclusive)\r
 */\r
 template <class ElementType, class ElementComparator>\r
-static int findInsertIndexInSortedArray (ElementComparator& comparator,\r
+static int findInsertIndexInSortedArray ([[maybe_unused]] ElementComparator& comparator,\r
                                          ElementType* const array,\r
                                          const ElementType newElement,\r
                                          int firstElement,\r
@@ -131,9 +131,6 @@ static int findInsertIndexInSortedArray (ElementComparator& comparator,
 {\r
     jassert (firstElement <= lastElement);\r
 \r
-    ignoreUnused (comparator); // if you pass in an object with a static compareElements() method, this\r
-                               // avoids getting warning messages about the parameter being unused\r
-\r
     while (firstElement < lastElement)\r
     {\r
         if (comparator.compareElements (newElement, array [firstElement]) == 0)\r
index 6e2333ce9889da749a28b736df471569a72e6057..b7609278e3b83093fdcbc97080c60667e1c966a7 100644 (file)
 namespace juce\r
 {\r
 \r
-namespace detail\r
-{\r
-namespace adlSwap\r
-{\r
-using std::swap;\r
-\r
-template <typename T>\r
-constexpr auto isNothrowSwappable = noexcept (swap (std::declval<T&>(), std::declval<T&>()));\r
-} // namespace adlSwap\r
-} // namespace detail\r
-\r
-/** A type representing the null state of an Optional.\r
-    Similar to std::nullopt_t.\r
-*/\r
-struct Nullopt\r
-{\r
-    explicit constexpr Nullopt (int) {}\r
-};\r
-\r
-/** An object that can be used when constructing and comparing Optional instances.\r
-    Similar to std::nullopt.\r
-*/\r
-constexpr Nullopt nullopt { 0 };\r
+using Nullopt = std::nullopt_t;\r
+constexpr auto nullopt = std::nullopt;\r
 \r
 // Without this, our tests can emit "unreachable code" warnings during\r
 // link time code generation.\r
 JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)\r
 \r
+#define JUCE_OPTIONAL_OPERATORS X(==) X(!=) X(<) X(<=) X(>) X(>=)\r
+\r
 /**\r
     A simple optional type.\r
 \r
-    Has similar (not necessarily identical!) semantics to std::optional.\r
+    In new code, you should probably prefer using std::optional directly.\r
 \r
     This is intended to stand-in for std::optional while JUCE's minimum\r
     supported language standard is lower than C++17. When the minimum language\r
@@ -72,224 +53,104 @@ JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4702)
 template <typename Value>\r
 class Optional\r
 {\r
-    template <typename T, typename U>\r
-    struct NotConstructibleFromSimilarType\r
-    {\r
-        static constexpr auto value = ! std::is_constructible<T, Optional<U>&>::value\r
-                                   && ! std::is_constructible<T, const Optional<U>&>::value\r
-                                   && ! std::is_constructible<T, Optional<U>&&>::value\r
-                                   && ! std::is_constructible<T, const Optional<U>&&>::value\r
-                                   && ! std::is_convertible<Optional<U>&, T>::value\r
-                                   && ! std::is_convertible<const Optional<U>&, T>::value\r
-                                   && ! std::is_convertible<Optional<U>&&, T>::value\r
-                                   && ! std::is_convertible<const Optional<U>&&, T>::value;\r
-    };\r
-\r
-    template <typename T, typename U>\r
-    using OptionalCopyConstructorEnabled = std::enable_if_t<std::is_constructible<T, const U&>::value && NotConstructibleFromSimilarType<T, U>::value>;\r
-\r
-    template <typename T, typename U>\r
-    using OptionalMoveConstructorEnabled = std::enable_if_t<std::is_constructible<T, U&&>::value && NotConstructibleFromSimilarType<T, U>::value>;\r
-\r
-    template <typename T, typename U>\r
-    static auto notAssignableFromSimilarType = NotConstructibleFromSimilarType<T, U>::value\r
-                                               && ! std::is_assignable<T&, Optional<U>&>::value\r
-                                               && ! std::is_assignable<T&, const Optional<U>&>::value\r
-                                               && ! std::is_assignable<T&, Optional<U>&&>::value\r
-                                               && ! std::is_assignable<T&, const Optional<U>&&>::value;\r
-\r
-    template <typename T, typename U>\r
-    using OptionalCopyAssignmentEnabled = std::enable_if_t<std::is_constructible<T, const U&>::value\r
-                                                           && std::is_assignable<T&, const U&>::value\r
-                                                           && NotConstructibleFromSimilarType<T, U>::value>;\r
-\r
-    template <typename T, typename U>\r
-    using OptionalMoveAssignmentEnabled = std::enable_if_t<std::is_constructible<T, U>::value\r
-                                                           && std::is_nothrow_assignable<T&, U>::value\r
-                                                           && NotConstructibleFromSimilarType<T, U>::value>;\r
+    template <typename>   struct IsOptional              : std::false_type {};\r
+    template <typename T> struct IsOptional<Optional<T>> : std::true_type  {};\r
 \r
 public:\r
-    Optional() : placeholder() {}\r
-\r
-    Optional (Nullopt) noexcept : placeholder() {}\r
-\r
-    template <typename U = Value,\r
-              typename = std::enable_if_t<std::is_constructible<Value, U&&>::value\r
-                                          && ! std::is_same<std::decay_t<U>, Optional>::value>>\r
-    Optional (U&& value) noexcept (noexcept (Value (std::forward<U> (value))))\r
-        : storage (std::forward<U> (value)), valid (true)\r
-    {\r
-    }\r
-\r
-    Optional (Optional&& other) noexcept (noexcept (std::declval<Optional>().constructFrom (other)))\r
-        : placeholder()\r
-    {\r
-        constructFrom (other);\r
-    }\r
+    Optional() = default;\r
+    Optional (const Optional&) = default;\r
+    Optional (Optional&&) = default;\r
+    Optional& operator= (const Optional&) = default;\r
+    Optional& operator= (Optional&&) = default;\r
 \r
-    Optional (const Optional& other)\r
-        : placeholder(), valid (other.valid)\r
-    {\r
-        if (valid)\r
-            new (&storage) Value (*other);\r
-    }\r
+    Optional (Nullopt) noexcept {}\r
 \r
-    template <typename Other, typename = OptionalMoveConstructorEnabled<Value, Other>>\r
-    Optional (Optional<Other>&& other) noexcept (noexcept (std::declval<Optional>().constructFrom (other)))\r
-        : placeholder()\r
-    {\r
-        constructFrom (other);\r
-    }\r
+    template <typename Head, typename... Tail, std::enable_if_t<! IsOptional<std::decay_t<Head>>::value, int> = 0>\r
+    Optional (Head&& head, Tail&&... tail)\r
+        noexcept (std::is_nothrow_constructible_v<std::optional<Value>, Head, Tail...>)\r
+        : opt (std::forward<Head> (head), std::forward<Tail> (tail)...) {}\r
 \r
-    template <typename Other, typename = OptionalCopyConstructorEnabled<Value, Other>>\r
+    template <typename Other>\r
     Optional (const Optional<Other>& other)\r
-        : placeholder(), valid (other.hasValue())\r
-    {\r
-        if (valid)\r
-            new (&storage) Value (*other);\r
-    }\r
+        noexcept (std::is_nothrow_constructible_v<std::optional<Value>, const std::optional<Other>&>)\r
+        : opt (other.opt) {}\r
 \r
-    Optional& operator= (Nullopt) noexcept\r
-    {\r
-        reset();\r
-        return *this;\r
-    }\r
+    template <typename Other>\r
+    Optional (Optional<Other>&& other)\r
+        noexcept (std::is_nothrow_constructible_v<std::optional<Value>, std::optional<Other>&&>)\r
+        : opt (std::move (other.opt)) {}\r
 \r
-    template <typename U = Value,\r
-              typename = std::enable_if_t<std::is_nothrow_move_constructible<U>::value\r
-                                          && std::is_nothrow_move_assignable<U>::value>>\r
-    Optional& operator= (Optional&& other) noexcept (noexcept (std::declval<Optional>().assign (std::declval<Optional&>())))\r
+    template <typename Other, std::enable_if_t<! IsOptional<std::decay_t<Other>>::value, int> = 0>\r
+    Optional& operator= (Other&& other)\r
+        noexcept (std::is_nothrow_assignable_v<std::optional<Value>, Other>)\r
     {\r
-        assign (other);\r
+        opt = std::forward<Other> (other);\r
         return *this;\r
     }\r
 \r
-    template <typename U = Value,\r
-              typename = std::enable_if_t<! std::is_same<std::decay_t<U>, Optional>::value\r
-                                          && std::is_constructible<Value, U>::value\r
-                                          && std::is_assignable<Value&, U>::value\r
-                                          && (! std::is_scalar<Value>::value || ! std::is_same<std::decay_t<U>, Value>::value)>>\r
-    Optional& operator= (U&& value)\r
+    template <typename Other>\r
+    Optional& operator= (const Optional<Other>& other)\r
+        noexcept (std::is_nothrow_assignable_v<std::optional<Value>, const std::optional<Other>&>)\r
     {\r
-        if (valid)\r
-            **this = std::forward<U> (value);\r
-        else\r
-            new (&storage) Value (std::forward<U> (value));\r
-\r
-        valid = true;\r
+        opt = other.opt;\r
         return *this;\r
     }\r
 \r
-    /** Maintains the strong exception safety guarantee. */\r
-    Optional& operator= (const Optional& other)\r
+    template <typename Other>\r
+    Optional& operator= (Optional<Other>&& other)\r
+        noexcept (std::is_nothrow_assignable_v<std::optional<Value>, std::optional<Other>&&>)\r
     {\r
-        auto copy = other;\r
-        assign (copy);\r
+        opt = std::move (other.opt);\r
         return *this;\r
     }\r
 \r
-    template <typename Other, typename = OptionalMoveAssignmentEnabled<Value, Other>>\r
-    Optional& operator= (Optional<Other>&& other) noexcept (noexcept (std::declval<Optional>().assign (other)))\r
+    template <typename... Other>\r
+    auto& emplace (Other&&... other)\r
     {\r
-        assign (other);\r
-        return *this;\r
+        return opt.emplace (std::forward<Other> (other)...);\r
     }\r
 \r
-    /** Maintains the strong exception safety guarantee. */\r
-    template <typename Other, typename = OptionalCopyAssignmentEnabled<Value, Other>>\r
-    Optional& operator= (const Optional<Other>& other)\r
+    void reset() noexcept\r
     {\r
-        auto copy = other;\r
-        assign (copy);\r
-        return *this;\r
+        opt.reset();\r
     }\r
 \r
-    ~Optional() noexcept\r
+    void swap (Optional& other)\r
+        noexcept (std::is_nothrow_swappable_v<std::optional<Value>>)\r
     {\r
-        reset();\r
+        opt.swap (other.opt);\r
     }\r
 \r
-          Value* operator->()       noexcept { return reinterpret_cast<      Value*> (&storage); }\r
-    const Value* operator->() const noexcept { return reinterpret_cast<const Value*> (&storage); }\r
-\r
-          Value& operator*()       noexcept { return *operator->(); }\r
-    const Value& operator*() const noexcept { return *operator->(); }\r
+    decltype (auto) operator->()       { return opt.operator->(); }\r
+    decltype (auto) operator->() const { return opt.operator->(); }\r
+    decltype (auto) operator* ()       { return opt.operator* (); }\r
+    decltype (auto) operator* () const { return opt.operator* (); }\r
 \r
-    explicit operator bool() const noexcept { return valid; }\r
-    bool hasValue() const noexcept { return valid; }\r
+    explicit operator bool() const noexcept { return opt.has_value(); }\r
+    bool hasValue() const noexcept { return opt.has_value(); }\r
 \r
-    void reset()\r
-    {\r
-        if (std::exchange (valid, false))\r
-            operator*().~Value();\r
-    }\r
+    template <typename U>\r
+    decltype (auto) orFallback (U&& fallback) const& { return opt.value_or (std::forward<U> (fallback)); }\r
 \r
-    /** Like std::optional::value_or */\r
     template <typename U>\r
-    Value orFallback (U&& fallback) const { return *this ? **this : std::forward<U> (fallback); }\r
+    decltype (auto) orFallback (U&& fallback) & { return opt.value_or (std::forward<U> (fallback)); }\r
 \r
-    template <typename... Args>\r
-    Value& emplace (Args&&... args)\r
-    {\r
-        reset();\r
-        new (&storage) Value (std::forward<Args> (args)...);\r
-        valid = true;\r
-        return **this;\r
-    }\r
+    #define X(op) \\r
+        template <typename T, typename U> friend bool operator op (const Optional<T>&, const Optional<U>&); \\r
+        template <typename T> friend bool operator op (const Optional<T>&, Nullopt); \\r
+        template <typename T> friend bool operator op (Nullopt, const Optional<T>&); \\r
+        template <typename T, typename U> friend bool operator op (const Optional<T>&, const U&); \\r
+        template <typename T, typename U> friend bool operator op (const T&, const Optional<U>&);\r
 \r
-    void swap (Optional& other) noexcept (std::is_nothrow_move_constructible<Value>::value\r
-                                          && detail::adlSwap::isNothrowSwappable<Value>)\r
-    {\r
-        if (hasValue() && other.hasValue())\r
-        {\r
-            using std::swap;\r
-            swap (**this, *other);\r
-        }\r
-        else if (hasValue() || other.hasValue())\r
-        {\r
-            (hasValue() ? other : *this).constructFrom (hasValue() ? *this : other);\r
-        }\r
-    }\r
-\r
-private:\r
-    template <typename Other>\r
-    void constructFrom (Optional<Other>& other) noexcept (noexcept (Value (std::move (*other))))\r
-    {\r
-        if (! other.hasValue())\r
-            return;\r
+    JUCE_OPTIONAL_OPERATORS\r
 \r
-        new (&storage) Value (std::move (*other));\r
-        valid = true;\r
-        other.reset();\r
-    }\r
+    #undef X\r
 \r
+private:\r
     template <typename Other>\r
-    void assign (Optional<Other>& other) noexcept (noexcept (std::declval<Value&>() = std::move (*other)) && noexcept (std::declval<Optional>().constructFrom (other)))\r
-    {\r
-        if (valid)\r
-        {\r
-            if (other.hasValue())\r
-            {\r
-                **this = std::move (*other);\r
-                other.reset();\r
-            }\r
-            else\r
-            {\r
-                reset();\r
-            }\r
-        }\r
-        else\r
-        {\r
-            constructFrom (other);\r
-        }\r
-    }\r
+    friend class Optional;\r
 \r
-    union\r
-    {\r
-        char placeholder;\r
-        Value storage;\r
-    };\r
-    bool valid = false;\r
+    std::optional<Value> opt;\r
 };\r
 \r
 JUCE_END_IGNORE_WARNINGS_MSVC\r
@@ -300,102 +161,17 @@ Optional<std::decay_t<Value>> makeOptional (Value&& v)
     return std::forward<Value> (v);\r
 }\r
 \r
-template <class T, class U>\r
-bool operator== (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
-    if (lhs.hasValue() != rhs.hasValue()) return false;\r
-    if (! lhs.hasValue()) return true;\r
-    return *lhs == *rhs;\r
-}\r
+#define X(op) \\r
+    template <typename T, typename U> bool operator op (const Optional<T>& lhs, const Optional<U>& rhs) { return lhs.opt op rhs.opt; } \\r
+    template <typename T> bool operator op (const Optional<T>& lhs, Nullopt rhs) { return lhs.opt op rhs; } \\r
+    template <typename T> bool operator op (Nullopt lhs, const Optional<T>& rhs) { return lhs op rhs.opt; } \\r
+    template <typename T, typename U> bool operator op (const Optional<T>& lhs, const U& rhs) { return lhs.opt op rhs; } \\r
+    template <typename T, typename U> bool operator op (const T& lhs, const Optional<U>& rhs) { return lhs op rhs.opt; }\r
 \r
-template <class T, class U>\r
-bool operator!= (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
-    if (lhs.hasValue() != rhs.hasValue()) return true;\r
-    if (! lhs.hasValue()) return false;\r
-    return *lhs != *rhs;\r
-}\r
-\r
-template <class T, class U>\r
-bool operator< (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
-    if (! rhs.hasValue()) return false;\r
-    if (! lhs.hasValue()) return true;\r
-    return *lhs < *rhs;\r
-}\r
+JUCE_OPTIONAL_OPERATORS\r
 \r
-template <class T, class U>\r
-bool operator<= (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
-    if (! lhs.hasValue()) return true;\r
-    if (! rhs.hasValue()) return false;\r
-    return *lhs <= *rhs;\r
-}\r
-\r
-template <class T, class U>\r
-bool operator> (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
-    if (! lhs.hasValue()) return false;\r
-    if (! rhs.hasValue()) return true;\r
-    return *lhs > *rhs;\r
-}\r
-\r
-template <class T, class U>\r
-bool operator>= (const Optional<T>& lhs, const Optional<U>& rhs)\r
-{\r
-    if (! rhs.hasValue()) return true;\r
-    if (! lhs.hasValue()) return false;\r
-    return *lhs >= *rhs;\r
-}\r
+#undef X\r
 \r
-template <class T>\r
-bool operator== (const Optional<T>& opt, Nullopt) noexcept { return ! opt.hasValue(); }\r
-template <class T>\r
-bool operator== (Nullopt, const Optional<T>& opt) noexcept { return ! opt.hasValue(); }\r
-template <class T>\r
-bool operator!= (const Optional<T>& opt, Nullopt) noexcept { return opt.hasValue(); }\r
-template <class T>\r
-bool operator!= (Nullopt, const Optional<T>& opt) noexcept { return opt.hasValue(); }\r
-template <class T>\r
-bool operator< (const Optional<T>&, Nullopt) noexcept { return false; }\r
-template <class T>\r
-bool operator< (Nullopt, const Optional<T>& opt) noexcept { return opt.hasValue(); }\r
-template <class T>\r
-bool operator<= (const Optional<T>& opt, Nullopt) noexcept { return ! opt.hasValue(); }\r
-template <class T>\r
-bool operator<= (Nullopt, const Optional<T>&) noexcept { return true; }\r
-template <class T>\r
-bool operator> (const Optional<T>& opt, Nullopt) noexcept { return opt.hasValue(); }\r
-template <class T>\r
-bool operator> (Nullopt, const Optional<T>&) noexcept { return false; }\r
-template <class T>\r
-bool operator>= (const Optional<T>&, Nullopt) noexcept { return true; }\r
-template <class T>\r
-bool operator>= (Nullopt, const Optional<T>& opt) noexcept { return ! opt.hasValue(); }\r
-\r
-template <class T, class U>\r
-bool operator== (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt == value : false; }\r
-template <class T, class U>\r
-bool operator== (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value == *opt : false; }\r
-template <class T, class U>\r
-bool operator!= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt != value : true; }\r
-template <class T, class U>\r
-bool operator!= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value != *opt : true; }\r
-template <class T, class U>\r
-bool operator< (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt < value : true; }\r
-template <class T, class U>\r
-bool operator< (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value < *opt : false; }\r
-template <class T, class U>\r
-bool operator<= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt <= value : true; }\r
-template <class T, class U>\r
-bool operator<= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value <= *opt : false; }\r
-template <class T, class U>\r
-bool operator> (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt > value : false; }\r
-template <class T, class U>\r
-bool operator> (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value > *opt : true; }\r
-template <class T, class U>\r
-bool operator>= (const Optional<T>& opt, const U& value) { return opt.hasValue() ? *opt >= value : false; }\r
-template <class T, class U>\r
-bool operator>= (const T& value, const Optional<U>& opt) { return opt.hasValue() ? value >= *opt : true; }\r
+#undef JUCE_OPTIONAL_OPERATORS\r
 \r
 } // namespace juce\r
index cc2b7994a84aef95c3b151bf26ed667691dbd0bf..b3e10de812ac18118a59e44d163790ed7f566dd3 100644 (file)
@@ -66,7 +66,8 @@ public:
             Optional<Ptr> original (ptr);\r
             expect (ptr.use_count() == 2);\r
             auto other = std::move (original);\r
-            expect (! original.hasValue());\r
+            // A moved-from optional still contains a value!\r
+            expect (original.hasValue());\r
             expect (other.hasValue());\r
             expect (ptr.use_count() == 2);\r
         }\r
@@ -104,7 +105,7 @@ public:
             aOpt = std::move (bOpt);\r
 \r
             expect (aOpt.hasValue());\r
-            expect (bOpt.hasValue());\r
+            expect (bOpt.hasValue());\r
 \r
             expect (a.use_count() == 1);\r
             expect (b.use_count() == 2);\r
@@ -158,7 +159,7 @@ public:
             empty = std::move (aOpt);\r
 \r
             expect (empty.hasValue());\r
-            expect (aOpt.hasValue());\r
+            expect (aOpt.hasValue());\r
 \r
             expect (a.use_count() == 2);\r
         }\r
@@ -265,7 +266,7 @@ public:
             expect (! a.hasValue());\r
         }\r
 \r
-        beginTest ("Strong exception safety is maintained when copying over populated object");\r
+        beginTest ("Exception safety of contained type is maintained when copying over populated object");\r
         {\r
             bool threw = false;\r
             Optional<ThrowOnCopy> a = ThrowOnCopy();\r
@@ -283,7 +284,7 @@ public:
 \r
             expect (threw);\r
             expect (a.hasValue());\r
-            expect (a->value == 5);\r
+            expect (a->value == -100);\r
         }\r
 \r
         beginTest ("Assigning from nullopt clears the instance");\r
index 5bc789eda7692803193636e57db1512228ec4fe2..c89b11255a7fa3fc003341215dc076c44444eb20 100644 (file)
@@ -46,7 +46,6 @@ namespace juce
 */\r
 template <class ObjectClass,\r
           class TypeOfCriticalSectionToUse = DummyCriticalSection>\r
-\r
 class OwnedArray\r
 {\r
 public:\r
@@ -531,17 +530,7 @@ public:
         @see add, sort, indexOfSorted\r
     */\r
     template <class ElementComparator>\r
-    int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept\r
-    {\r
-        // If you pass in an object with a static compareElements() method, this\r
-        // avoids getting warning messages about the parameter being unused\r
-        ignoreUnused (comparator);\r
-\r
-        const ScopedLockType lock (getLock());\r
-        auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());\r
-        insert (index, newObject);\r
-        return index;\r
-    }\r
+    int addSorted (ElementComparator& comparator, ObjectClass* newObject) noexcept;\r
 \r
     /** Finds the index of an object in the array, assuming that the array is sorted.\r
 \r
@@ -556,33 +545,7 @@ public:
         @see addSorted, sort\r
     */\r
     template <typename ElementComparator>\r
-    int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept\r
-    {\r
-        // If you pass in an object with a static compareElements() method, this\r
-        // avoids getting warning messages about the parameter being unused\r
-        ignoreUnused (comparator);\r
-\r
-        const ScopedLockType lock (getLock());\r
-        int s = 0, e = values.size();\r
-\r
-        while (s < e)\r
-        {\r
-            if (comparator.compareElements (objectToLookFor, values[s]) == 0)\r
-                return s;\r
-\r
-            auto halfway = (s + e) / 2;\r
-\r
-            if (halfway == s)\r
-                break;\r
-\r
-            if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)\r
-                s = halfway;\r
-            else\r
-                e = halfway;\r
-        }\r
-\r
-        return -1;\r
-    }\r
+    int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept;\r
 \r
     //==============================================================================\r
     /** Removes an object from the array.\r
@@ -818,18 +781,7 @@ public:
         @see sortArray, indexOfSorted\r
     */\r
     template <class ElementComparator>\r
-    void sort (ElementComparator& comparator,\r
-               bool retainOrderOfEquivalentItems = false) noexcept\r
-    {\r
-        // If you pass in an object with a static compareElements() method, this\r
-        // avoids getting warning messages about the parameter being unused\r
-        ignoreUnused (comparator);\r
-\r
-        const ScopedLockType lock (getLock());\r
-\r
-        if (size() > 1)\r
-            sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);\r
-    }\r
+    void sort (ElementComparator& comparator, bool retainOrderOfEquivalentItems = false) noexcept;\r
 \r
     //==============================================================================\r
     /** Returns the CriticalSection that locks this array.\r
@@ -870,4 +822,57 @@ private:
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (OwnedArray)\r
 };\r
 \r
+//==============================================================================\r
+template <class ObjectClass, class TypeOfCriticalSectionToUse>\r
+template <class ElementComparator>\r
+int OwnedArray<ObjectClass, TypeOfCriticalSectionToUse>::addSorted (\r
+    [[maybe_unused]] ElementComparator& comparator,\r
+    ObjectClass* newObject) noexcept\r
+{\r
+    const ScopedLockType lock (getLock());\r
+    auto index = findInsertIndexInSortedArray (comparator, values.begin(), newObject, 0, values.size());\r
+    insert (index, newObject);\r
+    return index;\r
+}\r
+\r
+template <class ObjectClass, class TypeOfCriticalSectionToUse>\r
+template <typename ElementComparator>\r
+int OwnedArray<ObjectClass, TypeOfCriticalSectionToUse>::indexOfSorted (\r
+    [[maybe_unused]] ElementComparator& comparator,\r
+    const ObjectClass* objectToLookFor) const noexcept\r
+{\r
+    const ScopedLockType lock (getLock());\r
+    int s = 0, e = values.size();\r
+\r
+    while (s < e)\r
+    {\r
+        if (comparator.compareElements (objectToLookFor, values[s]) == 0)\r
+            return s;\r
+\r
+        auto halfway = (s + e) / 2;\r
+\r
+        if (halfway == s)\r
+            break;\r
+\r
+        if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)\r
+            s = halfway;\r
+        else\r
+            e = halfway;\r
+    }\r
+\r
+    return -1;\r
+}\r
+\r
+template <class ObjectClass, class TypeOfCriticalSectionToUse>\r
+template <typename ElementComparator>\r
+void OwnedArray<ObjectClass, TypeOfCriticalSectionToUse>::sort (\r
+    [[maybe_unused]] ElementComparator& comparator,\r
+    bool retainOrderOfEquivalentItems) noexcept\r
+{\r
+    const ScopedLockType lock (getLock());\r
+\r
+    if (size() > 1)\r
+        sortArray (comparator, values.begin(), 0, size() - 1, retainOrderOfEquivalentItems);\r
+}\r
+\r
 } // namespace juce\r
index c281a1c4c1b8042721b01114d27b9b1d95158839..fe7dbdf55a896f83892dac49576493f8f5580a1a 100644 (file)
@@ -563,31 +563,7 @@ public:
         @see addSorted, sort\r
     */\r
     template <class ElementComparator>\r
-    int indexOfSorted (ElementComparator& comparator,\r
-                       const ObjectClass* objectToLookFor) const noexcept\r
-    {\r
-        ignoreUnused (comparator);\r
-        const ScopedLockType lock (getLock());\r
-        int s = 0, e = values.size();\r
-\r
-        while (s < e)\r
-        {\r
-            if (comparator.compareElements (objectToLookFor, values[s]) == 0)\r
-                return s;\r
-\r
-            auto halfway = (s + e) / 2;\r
-\r
-            if (halfway == s)\r
-                break;\r
-\r
-            if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)\r
-                s = halfway;\r
-            else\r
-                e = halfway;\r
-        }\r
-\r
-        return -1;\r
-    }\r
+    int indexOfSorted (ElementComparator& comparator, const ObjectClass* objectToLookFor) const noexcept;\r
 \r
     //==============================================================================\r
     /** Removes an object from the array.\r
@@ -828,16 +804,7 @@ public:
         @see sortArray\r
     */\r
     template <class ElementComparator>\r
-    void sort (ElementComparator& comparator,\r
-               bool retainOrderOfEquivalentItems = false) noexcept\r
-    {\r
-        // If you pass in an object with a static compareElements() method, this\r
-        // avoids getting warning messages about the parameter being unused\r
-        ignoreUnused (comparator);\r
-\r
-        const ScopedLockType lock (getLock());\r
-        sortArray (comparator, values.begin(), 0, values.size() - 1, retainOrderOfEquivalentItems);\r
-    }\r
+    void sort (ElementComparator& comparator, bool retainOrderOfEquivalentItems = false) noexcept;\r
 \r
     //==============================================================================\r
     /** Reduces the amount of storage being used by the array.\r
@@ -904,4 +871,43 @@ private:
     }\r
 };\r
 \r
+//==============================================================================\r
+template <class ObjectClass, class TypeOfCriticalSectionToUse>\r
+template <class ElementComparator>\r
+int ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>::indexOfSorted (\r
+    [[maybe_unused]] ElementComparator& comparator,\r
+    const ObjectClass* objectToLookFor) const noexcept\r
+{\r
+    const ScopedLockType lock (getLock());\r
+    int s = 0, e = values.size();\r
+\r
+    while (s < e)\r
+    {\r
+        if (comparator.compareElements (objectToLookFor, values[s]) == 0)\r
+            return s;\r
+\r
+        auto halfway = (s + e) / 2;\r
+\r
+        if (halfway == s)\r
+            break;\r
+\r
+        if (comparator.compareElements (objectToLookFor, values[halfway]) >= 0)\r
+            s = halfway;\r
+        else\r
+            e = halfway;\r
+    }\r
+\r
+    return -1;\r
+}\r
+\r
+template <class ObjectClass, class TypeOfCriticalSectionToUse>\r
+template <class ElementComparator>\r
+void ReferenceCountedArray<ObjectClass, TypeOfCriticalSectionToUse>::sort (\r
+    [[maybe_unused]] ElementComparator& comparator,\r
+    bool retainOrderOfEquivalentItems) noexcept\r
+{\r
+    const ScopedLockType lock (getLock());\r
+    sortArray (comparator, values.begin(), 0, values.size() - 1, retainOrderOfEquivalentItems);\r
+}\r
+\r
 } // namespace juce\r
index 2321da3d81c3332a97b20db30c53c63ed4ba0c3c..e84baa02af19e2097680e9ec6343d6dadc19eced 100644 (file)
@@ -493,18 +493,6 @@ struct var::Instance
     static constexpr VariantType attributesObject         { VariantType::ObjectTag{} };\r
 };\r
 \r
-constexpr var::VariantType var::Instance::attributesVoid;\r
-constexpr var::VariantType var::Instance::attributesUndefined;\r
-constexpr var::VariantType var::Instance::attributesInt;\r
-constexpr var::VariantType var::Instance::attributesInt64;\r
-constexpr var::VariantType var::Instance::attributesBool;\r
-constexpr var::VariantType var::Instance::attributesDouble;\r
-constexpr var::VariantType var::Instance::attributesMethod;\r
-constexpr var::VariantType var::Instance::attributesArray;\r
-constexpr var::VariantType var::Instance::attributesString;\r
-constexpr var::VariantType var::Instance::attributesBinary;\r
-constexpr var::VariantType var::Instance::attributesObject;\r
-\r
 //==============================================================================\r
 var::var() noexcept : type (&Instance::attributesVoid) {}\r
 var::var (const VariantType& t) noexcept  : type (&t) {}\r
index 20561f3959d0f14fb35d14f957fba5479f78a7d4..d19f14b86886aa888ae9e83bb199b5c48f8287a7 100644 (file)
@@ -953,7 +953,7 @@ File File::createTempFile (StringRef fileNameEnding)
 }\r
 \r
 bool File::createSymbolicLink (const File& linkFileToCreate,\r
-                               const String& nativePathOfTarget,\r
+                               [[maybe_unused]] const String& nativePathOfTarget,\r
                                bool overwriteExisting)\r
 {\r
     if (linkFileToCreate.exists())\r
@@ -986,7 +986,6 @@ bool File::createSymbolicLink (const File& linkFileToCreate,
                                nativePathOfTarget.toWideCharPointer(),\r
                                targetFile.isDirectory() ? SYMBOLIC_LINK_FLAG_DIRECTORY : 0) != FALSE;\r
    #else\r
-    ignoreUnused (nativePathOfTarget);\r
     jassertfalse; // symbolic links not supported on this platform!\r
     return false;\r
    #endif\r
index 1cd0af2e1a9cd03f359d61a5cffa26be2c0b4866..6b4ad3981bfcf1a02a81314338a2152df3f4deb6 100644 (file)
@@ -67,14 +67,19 @@ File FileSearchPath::operator[] (int index) const
 }\r
 \r
 String FileSearchPath::toString() const\r
+{\r
+    return toStringWithSeparator (";");\r
+}\r
+\r
+String FileSearchPath::toStringWithSeparator (StringRef separator) const\r
 {\r
     auto dirs = directories;\r
 \r
     for (auto& d : dirs)\r
-        if (d.containsChar (';'))\r
+        if (d.contains (separator))\r
             d = d.quoted();\r
 \r
-    return dirs.joinIntoString (";");\r
+    return dirs.joinIntoString (separator);\r
 }\r
 \r
 void FileSearchPath::add (const File& dir, int insertIndex)\r
index 144419d0adf6cf312e40c82c6480b9b3b63f974b..8b48162ba515bbc33b6f8cd8a2b6868254f35a00 100644 (file)
@@ -78,6 +78,9 @@ public:
     /** Returns the search path as a semicolon-separated list of directories. */\r
     String toString() const;\r
 \r
+    /** Returns the search paths, joined with the provided separator. */\r
+    String toStringWithSeparator (StringRef separator) const;\r
+\r
     //==============================================================================\r
     /** Adds a new directory to the search path.\r
 \r
index 656600745b1b437a89ed47a9f84a5e03009ab867..42e150e93e283b6de41b9a7dade6451ac73f2f47 100644 (file)
 namespace juce\r
 {\r
 \r
-struct MimeTypeTableEntry\r
+namespace\r
 {\r
-    const char* fileExtension, *mimeType;\r
 \r
-    static MimeTypeTableEntry table[641];\r
+struct Entry\r
+{\r
+    const char* fileExtension;\r
+    const char* mimeType;\r
 };\r
 \r
-static StringArray getMatches (const String& toMatch,\r
-                               const char* MimeTypeTableEntry::* matchField,\r
-                               const char* MimeTypeTableEntry::* returnField)\r
+class Table\r
 {\r
-    StringArray result;\r
+public:\r
+    void addEntry (const Entry& entry)\r
+    {\r
+        typeForExtension.emplace (entry.fileExtension, entry.mimeType);\r
+        extensionForType.emplace (entry.mimeType, entry.fileExtension);\r
+    }\r
 \r
-    for (auto type : MimeTypeTableEntry::table)\r
-        if (toMatch == type.*matchField)\r
-            result.add (type.*returnField);\r
+    StringArray getTypesForExtension (const String& extension) const\r
+    {\r
+        return getValuesForKey (typeForExtension, extension);\r
+    }\r
 \r
-    return result;\r
-}\r
+    StringArray getExtensionsForType (const String& type) const\r
+    {\r
+        return getValuesForKey (extensionForType, type);\r
+    }\r
 \r
-namespace MimeTypeTable\r
-{\r
+    static Table& get()\r
+    {\r
+        static Table table;\r
+        return table;\r
+    }\r
+\r
+private:\r
+    Table() = default;\r
+\r
+    static StringArray getValuesForKey (const std::multimap<String, String>& map, const String& key)\r
+    {\r
+        const auto [begin, end] = map.equal_range (key);\r
+\r
+        StringArray result;\r
+        std::for_each (begin, end, [&] (const auto& pair) { result.add (pair.second); });\r
+\r
+        return result;\r
+    }\r
+\r
+    static inline constexpr Entry initialEntries[]\r
+    {\r
+        { "3dm",      "x-world/x-3dmf" },\r
+        { "3dmf",     "x-world/x-3dmf" },\r
+        { "a",        "application/octet-stream" },\r
+        { "aab",      "application/x-authorware-bin" },\r
+        { "aam",      "application/x-authorware-map" },\r
+        { "aas",      "application/x-authorware-seg" },\r
+        { "abc",      "text/vnd.abc" },\r
+        { "acgi",     "text/html" },\r
+        { "afl",      "video/animaflex" },\r
+        { "ai",       "application/postscript" },\r
+        { "aif",      "audio/aiff" },\r
+        { "aif",      "audio/x-aiff" },\r
+        { "aifc",     "audio/aiff" },\r
+        { "aifc",     "audio/x-aiff" },\r
+        { "aiff",     "audio/aiff" },\r
+        { "aiff",     "audio/x-aiff" },\r
+        { "aim",      "application/x-aim" },\r
+        { "aip",      "text/x-audiosoft-intra" },\r
+        { "ani",      "application/x-navi-animation" },\r
+        { "aos",      "application/x-nokia-9000-communicator-add-on-software" },\r
+        { "aps",      "application/mime" },\r
+        { "arc",      "application/octet-stream" },\r
+        { "arj",      "application/arj" },\r
+        { "arj",      "application/octet-stream" },\r
+        { "art",      "image/x-jg" },\r
+        { "asf",      "video/x-ms-asf" },\r
+        { "asm",      "text/x-asm" },\r
+        { "asp",      "text/asp" },\r
+        { "asx",      "application/x-mplayer2" },\r
+        { "asx",      "video/x-ms-asf" },\r
+        { "asx",      "video/x-ms-asf-plugin" },\r
+        { "au",       "audio/basic" },\r
+        { "au",       "audio/x-au" },\r
+        { "avi",      "application/x-troff-msvideo" },\r
+        { "avi",      "video/avi" },\r
+        { "avi",      "video/msvideo" },\r
+        { "avi",      "video/x-msvideo" },\r
+        { "avs",      "video/avs-video" },\r
+        { "bcpio",    "application/x-bcpio" },\r
+        { "bin",      "application/mac-binary" },\r
+        { "bin",      "application/macbinary" },\r
+        { "bin",      "application/octet-stream" },\r
+        { "bin",      "application/x-binary" },\r
+        { "bin",      "application/x-macbinary" },\r
+        { "bm",       "image/bmp" },\r
+        { "bmp",      "image/bmp" },\r
+        { "bmp",      "image/x-windows-bmp" },\r
+        { "boo",      "application/book" },\r
+        { "book",     "application/book" },\r
+        { "boz",      "application/x-bzip2" },\r
+        { "bsh",      "application/x-bsh" },\r
+        { "bz",       "application/x-bzip" },\r
+        { "bz2",      "application/x-bzip2" },\r
+        { "c",        "text/plain" },\r
+        { "c",        "text/x-c" },\r
+        { "c++",      "text/plain" },\r
+        { "cat",      "application/vnd.ms-pki.seccat" },\r
+        { "cc",       "text/plain" },\r
+        { "cc",       "text/x-c" },\r
+        { "ccad",     "application/clariscad" },\r
+        { "cco",      "application/x-cocoa" },\r
+        { "cdf",      "application/cdf" },\r
+        { "cdf",      "application/x-cdf" },\r
+        { "cdf",      "application/x-netcdf" },\r
+        { "cer",      "application/pkix-cert" },\r
+        { "cer",      "application/x-x509-ca-cert" },\r
+        { "cha",      "application/x-chat" },\r
+        { "chat",     "application/x-chat" },\r
+        { "class",    "application/java" },\r
+        { "class",    "application/java-byte-code" },\r
+        { "class",    "application/x-java-class" },\r
+        { "com",      "application/octet-stream" },\r
+        { "com",      "text/plain" },\r
+        { "conf",     "text/plain" },\r
+        { "cpio",     "application/x-cpio" },\r
+        { "cpp",      "text/x-c" },\r
+        { "cpt",      "application/mac-compactpro" },\r
+        { "cpt",      "application/x-compactpro" },\r
+        { "cpt",      "application/x-cpt" },\r
+        { "crl",      "application/pkcs-crl" },\r
+        { "crl",      "application/pkix-crl" },\r
+        { "crt",      "application/pkix-cert" },\r
+        { "crt",      "application/x-x509-ca-cert" },\r
+        { "crt",      "application/x-x509-user-cert" },\r
+        { "csh",      "application/x-csh" },\r
+        { "csh",      "text/x-script.csh" },\r
+        { "css",      "application/x-pointplus" },\r
+        { "css",      "text/css" },\r
+        { "cxx",      "text/plain" },\r
+        { "dcr",      "application/x-director" },\r
+        { "deepv",    "application/x-deepv" },\r
+        { "def",      "text/plain" },\r
+        { "der",      "application/x-x509-ca-cert" },\r
+        { "dif",      "video/x-dv" },\r
+        { "dir",      "application/x-director" },\r
+        { "dl",       "video/dl" },\r
+        { "dl",       "video/x-dl" },\r
+        { "doc",      "application/msword" },\r
+        { "dot",      "application/msword" },\r
+        { "dp",       "application/commonground" },\r
+        { "drw",      "application/drafting" },\r
+        { "dump",     "application/octet-stream" },\r
+        { "dv",       "video/x-dv" },\r
+        { "dvi",      "application/x-dvi" },\r
+        { "dwf",      "drawing/x-dwf" },\r
+        { "dwf",      "model/vnd.dwf" },\r
+        { "dwg",      "application/acad" },\r
+        { "dwg",      "image/vnd.dwg" },\r
+        { "dwg",      "image/x-dwg" },\r
+        { "dxf",      "application/dxf" },\r
+        { "dxf",      "image/vnd.dwg" },\r
+        { "dxf",      "image/x-dwg" },\r
+        { "dxr",      "application/x-director" },\r
+        { "el",       "text/x-script.elisp" },\r
+        { "elc",      "application/x-bytecode.elisp" },\r
+        { "elc",      "application/x-elc" },\r
+        { "env",      "application/x-envoy" },\r
+        { "eps",      "application/postscript" },\r
+        { "es",       "application/x-esrehber" },\r
+        { "etx",      "text/x-setext" },\r
+        { "evy",      "application/envoy" },\r
+        { "evy",      "application/x-envoy" },\r
+        { "exe",      "application/octet-stream" },\r
+        { "f",        "text/plain" },\r
+        { "f",        "text/x-fortran" },\r
+        { "f77",      "text/x-fortran" },\r
+        { "f90",      "text/plain" },\r
+        { "f90",      "text/x-fortran" },\r
+        { "fdf",      "application/vnd.fdf" },\r
+        { "fif",      "application/fractals" },\r
+        { "fif",      "image/fif" },\r
+        { "fli",      "video/fli" },\r
+        { "fli",      "video/x-fli" },\r
+        { "flo",      "image/florian" },\r
+        { "flx",      "text/vnd.fmi.flexstor" },\r
+        { "fmf",      "video/x-atomic3d-feature" },\r
+        { "for",      "text/plain" },\r
+        { "for",      "text/x-fortran" },\r
+        { "fpx",      "image/vnd.fpx" },\r
+        { "fpx",      "image/vnd.net-fpx" },\r
+        { "frl",      "application/freeloader" },\r
+        { "funk",     "audio/make" },\r
+        { "g",        "text/plain" },\r
+        { "g3",       "image/g3fax" },\r
+        { "gif",      "image/gif" },\r
+        { "gl",       "video/gl" },\r
+        { "gl",       "video/x-gl" },\r
+        { "gsd",      "audio/x-gsm" },\r
+        { "gsm",      "audio/x-gsm" },\r
+        { "gsp",      "application/x-gsp" },\r
+        { "gss",      "application/x-gss" },\r
+        { "gtar",     "application/x-gtar" },\r
+        { "gz",       "application/x-compressed" },\r
+        { "gz",       "application/x-gzip" },\r
+        { "gzip",     "application/x-gzip" },\r
+        { "gzip",     "multipart/x-gzip" },\r
+        { "h",        "text/plain" },\r
+        { "h",        "text/x-h" },\r
+        { "hdf",      "application/x-hdf" },\r
+        { "help",     "application/x-helpfile" },\r
+        { "hgl",      "application/vnd.hp-hpgl" },\r
+        { "hh",       "text/plain" },\r
+        { "hh",       "text/x-h" },\r
+        { "hlb",      "text/x-script" },\r
+        { "hlp",      "application/hlp" },\r
+        { "hlp",      "application/x-helpfile" },\r
+        { "hlp",      "application/x-winhelp" },\r
+        { "hpg",      "application/vnd.hp-hpgl" },\r
+        { "hpgl",     "application/vnd.hp-hpgl" },\r
+        { "hqx",      "application/binhex" },\r
+        { "hqx",      "application/binhex4" },\r
+        { "hqx",      "application/mac-binhex" },\r
+        { "hqx",      "application/mac-binhex40" },\r
+        { "hqx",      "application/x-binhex40" },\r
+        { "hqx",      "application/x-mac-binhex40" },\r
+        { "hta",      "application/hta" },\r
+        { "htc",      "text/x-component" },\r
+        { "htm",      "text/html" },\r
+        { "html",     "text/html" },\r
+        { "htmls",    "text/html" },\r
+        { "htt",      "text/webviewhtml" },\r
+        { "htx",      "text/html" },\r
+        { "ice",      "x-conference/x-cooltalk" },\r
+        { "ico",      "image/x-icon" },\r
+        { "idc",      "text/plain" },\r
+        { "ief",      "image/ief" },\r
+        { "iefs",     "image/ief" },\r
+        { "iges",     "application/iges" },\r
+        { "iges",     "model/iges" },\r
+        { "igs",      "application/iges" },\r
+        { "igs",      "model/iges" },\r
+        { "ima",      "application/x-ima" },\r
+        { "imap",     "application/x-httpd-imap" },\r
+        { "inf",      "application/inf" },\r
+        { "ins",      "application/x-internett-signup" },\r
+        { "ip",       "application/x-ip2" },\r
+        { "isu",      "video/x-isvideo" },\r
+        { "it",       "audio/it" },\r
+        { "iv",       "application/x-inventor" },\r
+        { "ivr",      "i-world/i-vrml" },\r
+        { "ivy",      "application/x-livescreen" },\r
+        { "jam",      "audio/x-jam" },\r
+        { "jav",      "text/plain" },\r
+        { "jav",      "text/x-java-source" },\r
+        { "java",     "text/plain" },\r
+        { "java",     "text/x-java-source" },\r
+        { "jcm",      "application/x-java-commerce" },\r
+        { "jfif",     "image/jpeg" },\r
+        { "jfif",     "image/pjpeg" },\r
+        { "jpe",      "image/jpeg" },\r
+        { "jpe",      "image/pjpeg" },\r
+        { "jpeg",     "image/jpeg" },\r
+        { "jpeg",     "image/pjpeg" },\r
+        { "jpg",      "image/jpeg" },\r
+        { "jpg",      "image/pjpeg" },\r
+        { "jps",      "image/x-jps" },\r
+        { "js",       "application/x-javascript" },\r
+        { "json",     "application/json" },\r
+        { "jut",      "image/jutvision" },\r
+        { "kar",      "audio/midi" },\r
+        { "kar",      "music/x-karaoke" },\r
+        { "ksh",      "application/x-ksh" },\r
+        { "ksh",      "text/x-script.ksh" },\r
+        { "la",       "audio/nspaudio" },\r
+        { "la",       "audio/x-nspaudio" },\r
+        { "lam",      "audio/x-liveaudio" },\r
+        { "latex",    "application/x-latex" },\r
+        { "lha",      "application/lha" },\r
+        { "lha",      "application/octet-stream" },\r
+        { "lha",      "application/x-lha" },\r
+        { "lhx",      "application/octet-stream" },\r
+        { "list",     "text/plain" },\r
+        { "lma",      "audio/nspaudio" },\r
+        { "lma",      "audio/x-nspaudio" },\r
+        { "log",      "text/plain" },\r
+        { "lsp",      "application/x-lisp" },\r
+        { "lsp",      "text/x-script.lisp" },\r
+        { "lst",      "text/plain" },\r
+        { "lsx",      "text/x-la-asf" },\r
+        { "ltx",      "application/x-latex" },\r
+        { "lzh",      "application/octet-stream" },\r
+        { "lzh",      "application/x-lzh" },\r
+        { "lzx",      "application/lzx" },\r
+        { "lzx",      "application/octet-stream" },\r
+        { "lzx",      "application/x-lzx" },\r
+        { "m",        "text/plain" },\r
+        { "m",        "text/x-m" },\r
+        { "m1v",      "video/mpeg" },\r
+        { "m2a",      "audio/mpeg" },\r
+        { "m2v",      "video/mpeg" },\r
+        { "m3u",      "audio/x-mpequrl" },\r
+        { "man",      "application/x-troff-man" },\r
+        { "map",      "application/x-navimap" },\r
+        { "mar",      "text/plain" },\r
+        { "mbd",      "application/mbedlet" },\r
+        { "mc$",      "application/x-magic-cap-package-1.0" },\r
+        { "mcd",      "application/mcad" },\r
+        { "mcd",      "application/x-mathcad" },\r
+        { "mcf",      "image/vasa" },\r
+        { "mcf",      "text/mcf" },\r
+        { "mcp",      "application/netmc" },\r
+        { "me",       "application/x-troff-me" },\r
+        { "mht",      "message/rfc822" },\r
+        { "mhtml",    "message/rfc822" },\r
+        { "mid",      "application/x-midi" },\r
+        { "mid",      "audio/midi" },\r
+        { "mid",      "audio/x-mid" },\r
+        { "mid",      "audio/x-midi" },\r
+        { "mid",      "music/crescendo" },\r
+        { "mid",      "x-music/x-midi" },\r
+        { "midi",     "application/x-midi" },\r
+        { "midi",     "audio/midi" },\r
+        { "midi",     "audio/x-mid" },\r
+        { "midi",     "audio/x-midi" },\r
+        { "midi",     "music/crescendo" },\r
+        { "midi",     "x-music/x-midi" },\r
+        { "mif",      "application/x-frame" },\r
+        { "mif",      "application/x-mif" },\r
+        { "mime",     "message/rfc822" },\r
+        { "mime",     "www/mime" },\r
+        { "mjf",      "audio/x-vnd.audioexplosion.mjuicemediafile" },\r
+        { "mjpg",     "video/x-motion-jpeg" },\r
+        { "mm",       "application/base64" },\r
+        { "mm",       "application/x-meme" },\r
+        { "mme",      "application/base64" },\r
+        { "mod",      "audio/mod" },\r
+        { "mod",      "audio/x-mod" },\r
+        { "moov",     "video/quicktime" },\r
+        { "mov",      "video/quicktime" },\r
+        { "movie",    "video/x-sgi-movie" },\r
+        { "mp2",      "audio/mpeg" },\r
+        { "mp2",      "audio/x-mpeg" },\r
+        { "mp2",      "video/mpeg" },\r
+        { "mp2",      "video/x-mpeg" },\r
+        { "mp2",      "video/x-mpeq2a" },\r
+        { "mp3",      "audio/mpeg" },\r
+        { "mp3",      "audio/mpeg3" },\r
+        { "mp3",      "audio/x-mpeg-3" },\r
+        { "mp3",      "video/mpeg" },\r
+        { "mp3",      "video/x-mpeg" },\r
+        { "mpa",      "audio/mpeg" },\r
+        { "mpa",      "video/mpeg" },\r
+        { "mpc",      "application/x-project" },\r
+        { "mpe",      "video/mpeg" },\r
+        { "mpeg",     "video/mpeg" },\r
+        { "mpg",      "audio/mpeg" },\r
+        { "mpg",      "video/mpeg" },\r
+        { "mpga",     "audio/mpeg" },\r
+        { "mpp",      "application/vnd.ms-project" },\r
+        { "mpt",      "application/x-project" },\r
+        { "mpv",      "application/x-project" },\r
+        { "mpx",      "application/x-project" },\r
+        { "mrc",      "application/marc" },\r
+        { "ms",       "application/x-troff-ms" },\r
+        { "mv",       "video/x-sgi-movie" },\r
+        { "my",       "audio/make" },\r
+        { "mzz",      "application/x-vnd.audioexplosion.mzz" },\r
+        { "nap",      "image/naplps" },\r
+        { "naplps",   "image/naplps" },\r
+        { "nc",       "application/x-netcdf" },\r
+        { "ncm",      "application/vnd.nokia.configuration-message" },\r
+        { "nif",      "image/x-niff" },\r
+        { "niff",     "image/x-niff" },\r
+        { "nix",      "application/x-mix-transfer" },\r
+        { "nsc",      "application/x-conference" },\r
+        { "nvd",      "application/x-navidoc" },\r
+        { "o",        "application/octet-stream" },\r
+        { "oda",      "application/oda" },\r
+        { "omc",      "application/x-omc" },\r
+        { "omcd",     "application/x-omcdatamaker" },\r
+        { "omcr",     "application/x-omcregerator" },\r
+        { "p",        "text/x-pascal" },\r
+        { "p10",      "application/pkcs10" },\r
+        { "p10",      "application/x-pkcs10" },\r
+        { "p12",      "application/pkcs-12" },\r
+        { "p12",      "application/x-pkcs12" },\r
+        { "p7a",      "application/x-pkcs7-signature" },\r
+        { "p7c",      "application/pkcs7-mime" },\r
+        { "p7c",      "application/x-pkcs7-mime" },\r
+        { "p7m",      "application/pkcs7-mime" },\r
+        { "p7m",      "application/x-pkcs7-mime" },\r
+        { "p7r",      "application/x-pkcs7-certreqresp" },\r
+        { "p7s",      "application/pkcs7-signature" },\r
+        { "part",     "application/pro_eng" },\r
+        { "pas",      "text/pascal" },\r
+        { "pbm",      "image/x-portable-bitmap" },\r
+        { "pcl",      "application/vnd.hp-pcl" },\r
+        { "pcl",      "application/x-pcl" },\r
+        { "pct",      "image/x-pict" },\r
+        { "pcx",      "image/x-pcx" },\r
+        { "pdb",      "chemical/x-pdb" },\r
+        { "pdf",      "application/pdf" },\r
+        { "pfunk",    "audio/make" },\r
+        { "pfunk",    "audio/make.my.funk" },\r
+        { "pgm",      "image/x-portable-graymap" },\r
+        { "pgm",      "image/x-portable-greymap" },\r
+        { "pic",      "image/pict" },\r
+        { "pict",     "image/pict" },\r
+        { "pkg",      "application/x-newton-compatible-pkg" },\r
+        { "pko",      "application/vnd.ms-pki.pko" },\r
+        { "pl",       "text/plain" },\r
+        { "pl",       "text/x-script.perl" },\r
+        { "plx",      "application/x-pixclscript" },\r
+        { "pm",       "image/x-xpixmap" },\r
+        { "pm",       "text/x-script.perl-module" },\r
+        { "pm4",      "application/x-pagemaker" },\r
+        { "pm5",      "application/x-pagemaker" },\r
+        { "png",      "image/png" },\r
+        { "pnm",      "application/x-portable-anymap" },\r
+        { "pnm",      "image/x-portable-anymap" },\r
+        { "pot",      "application/mspowerpoint" },\r
+        { "pot",      "application/vnd.ms-powerpoint" },\r
+        { "pov",      "model/x-pov" },\r
+        { "ppa",      "application/vnd.ms-powerpoint" },\r
+        { "ppm",      "image/x-portable-pixmap" },\r
+        { "pps",      "application/mspowerpoint" },\r
+        { "pps",      "application/vnd.ms-powerpoint" },\r
+        { "ppt",      "application/mspowerpoint" },\r
+        { "ppt",      "application/powerpoint" },\r
+        { "ppt",      "application/vnd.ms-powerpoint" },\r
+        { "ppt",      "application/x-mspowerpoint" },\r
+        { "ppz",      "application/mspowerpoint" },\r
+        { "pre",      "application/x-freelance" },\r
+        { "prt",      "application/pro_eng" },\r
+        { "ps",       "application/postscript" },\r
+        { "psd",      "application/octet-stream" },\r
+        { "pvu",      "paleovu/x-pv" },\r
+        { "pwz",      "application/vnd.ms-powerpoint" },\r
+        { "py",       "text/x-script.python" },\r
+        { "pyc",      "application/x-bytecode.python" },\r
+        { "qcp",      "audio/vnd.qcelp" },\r
+        { "qd3",      "x-world/x-3dmf" },\r
+        { "qd3d",     "x-world/x-3dmf" },\r
+        { "qif",      "image/x-quicktime" },\r
+        { "qt",       "video/quicktime" },\r
+        { "qtc",      "video/x-qtc" },\r
+        { "qti",      "image/x-quicktime" },\r
+        { "qtif",     "image/x-quicktime" },\r
+        { "ra",       "audio/x-pn-realaudio" },\r
+        { "ra",       "audio/x-pn-realaudio-plugin" },\r
+        { "ra",       "audio/x-realaudio" },\r
+        { "ram",      "audio/x-pn-realaudio" },\r
+        { "ras",      "application/x-cmu-raster" },\r
+        { "ras",      "image/cmu-raster" },\r
+        { "ras",      "image/x-cmu-raster" },\r
+        { "rast",     "image/cmu-raster" },\r
+        { "rexx",     "text/x-script.rexx" },\r
+        { "rf",       "image/vnd.rn-realflash" },\r
+        { "rgb",      "image/x-rgb" },\r
+        { "rm",       "application/vnd.rn-realmedia" },\r
+        { "rm",       "audio/x-pn-realaudio" },\r
+        { "rmi",      "audio/mid" },\r
+        { "rmm",      "audio/x-pn-realaudio" },\r
+        { "rmp",      "audio/x-pn-realaudio" },\r
+        { "rmp",      "audio/x-pn-realaudio-plugin" },\r
+        { "rng",      "application/ringing-tones" },\r
+        { "rng",      "application/vnd.nokia.ringing-tone" },\r
+        { "rnx",      "application/vnd.rn-realplayer" },\r
+        { "roff",     "application/x-troff" },\r
+        { "rp",       "image/vnd.rn-realpix" },\r
+        { "rpm",      "audio/x-pn-realaudio-plugin" },\r
+        { "rt",       "text/richtext" },\r
+        { "rt",       "text/vnd.rn-realtext" },\r
+        { "rtf",      "application/rtf" },\r
+        { "rtf",      "application/x-rtf" },\r
+        { "rtf",      "text/richtext" },\r
+        { "rtx",      "application/rtf" },\r
+        { "rtx",      "text/richtext" },\r
+        { "rv",       "video/vnd.rn-realvideo" },\r
+        { "s",        "text/x-asm" },\r
+        { "s3m",      "audio/s3m" },\r
+        { "saveme",   "application/octet-stream" },\r
+        { "sbk",      "application/x-tbook" },\r
+        { "scm",      "application/x-lotusscreencam" },\r
+        { "scm",      "text/x-script.guile" },\r
+        { "scm",      "text/x-script.scheme" },\r
+        { "scm",      "video/x-scm" },\r
+        { "sdml",     "text/plain" },\r
+        { "sdp",      "application/sdp" },\r
+        { "sdp",      "application/x-sdp" },\r
+        { "sdr",      "application/sounder" },\r
+        { "sea",      "application/sea" },\r
+        { "sea",      "application/x-sea" },\r
+        { "set",      "application/set" },\r
+        { "sgm",      "text/sgml" },\r
+        { "sgm",      "text/x-sgml" },\r
+        { "sgml",     "text/sgml" },\r
+        { "sgml",     "text/x-sgml" },\r
+        { "sh",       "application/x-bsh" },\r
+        { "sh",       "application/x-sh" },\r
+        { "sh",       "application/x-shar" },\r
+        { "sh",       "text/x-script.sh" },\r
+        { "shar",     "application/x-bsh" },\r
+        { "shar",     "application/x-shar" },\r
+        { "shtml",    "text/html" },\r
+        { "shtml",    "text/x-server-parsed-html" },\r
+        { "sid",      "audio/x-psid" },\r
+        { "sit",      "application/x-sit" },\r
+        { "sit",      "application/x-stuffit" },\r
+        { "skd",      "application/x-koan" },\r
+        { "skm",      "application/x-koan" },\r
+        { "skp",      "application/x-koan" },\r
+        { "skt",      "application/x-koan" },\r
+        { "sl",       "application/x-seelogo" },\r
+        { "smi",      "application/smil" },\r
+        { "smil",     "application/smil" },\r
+        { "snd",      "audio/basic" },\r
+        { "snd",      "audio/x-adpcm" },\r
+        { "sol",      "application/solids" },\r
+        { "spc",      "application/x-pkcs7-certificates" },\r
+        { "spc",      "text/x-speech" },\r
+        { "spl",      "application/futuresplash" },\r
+        { "spr",      "application/x-sprite" },\r
+        { "sprite",   "application/x-sprite" },\r
+        { "src",      "application/x-wais-source" },\r
+        { "ssi",      "text/x-server-parsed-html" },\r
+        { "ssm",      "application/streamingmedia" },\r
+        { "sst",      "application/vnd.ms-pki.certstore" },\r
+        { "step",     "application/step" },\r
+        { "stl",      "application/sla" },\r
+        { "stl",      "application/vnd.ms-pki.stl" },\r
+        { "stl",      "application/x-navistyle" },\r
+        { "stp",      "application/step" },\r
+        { "sv4cpio,", "application/x-sv4cpio" },\r
+        { "sv4crc",   "application/x-sv4crc" },\r
+        { "svf",      "image/vnd.dwg" },\r
+        { "svf",      "image/x-dwg" },\r
+        { "svr",      "application/x-world" },\r
+        { "svr",      "x-world/x-svr" },\r
+        { "swf",      "application/x-shockwave-flash" },\r
+        { "t",        "application/x-troff" },\r
+        { "talk",     "text/x-speech" },\r
+        { "tar",      "application/x-tar" },\r
+        { "tbk",      "application/toolbook" },\r
+        { "tbk",      "application/x-tbook" },\r
+        { "tcl",      "application/x-tcl" },\r
+        { "tcl",      "text/x-script.tcl" },\r
+        { "tcsh",     "text/x-script.tcsh" },\r
+        { "tex",      "application/x-tex" },\r
+        { "texi",     "application/x-texinfo" },\r
+        { "texinfo,", "application/x-texinfo" },\r
+        { "text",     "application/plain" },\r
+        { "text",     "text/plain" },\r
+        { "tgz",      "application/gnutar" },\r
+        { "tgz",      "application/x-compressed" },\r
+        { "tif",      "image/tiff" },\r
+        { "tif",      "image/x-tiff" },\r
+        { "tiff",     "image/tiff" },\r
+        { "tiff",     "image/x-tiff" },\r
+        { "tr",       "application/x-troff" },\r
+        { "tsi",      "audio/tsp-audio" },\r
+        { "tsp",      "application/dsptype" },\r
+        { "tsp",      "audio/tsplayer" },\r
+        { "tsv",      "text/tab-separated-values" },\r
+        { "turbot",   "image/florian" },\r
+        { "txt",      "text/plain" },\r
+        { "uil",      "text/x-uil" },\r
+        { "uni",      "text/uri-list" },\r
+        { "unis",     "text/uri-list" },\r
+        { "unv",      "application/i-deas" },\r
+        { "uri",      "text/uri-list" },\r
+        { "uris",     "text/uri-list" },\r
+        { "ustar",    "application/x-ustar" },\r
+        { "ustar",    "multipart/x-ustar" },\r
+        { "uu",       "application/octet-stream" },\r
+        { "uu",       "text/x-uuencode" },\r
+        { "uue",      "text/x-uuencode" },\r
+        { "vcd",      "application/x-cdlink" },\r
+        { "vcs",      "text/x-vcalendar" },\r
+        { "vda",      "application/vda" },\r
+        { "vdo",      "video/vdo" },\r
+        { "vew",      "application/groupwise" },\r
+        { "viv",      "video/vivo" },\r
+        { "viv",      "video/vnd.vivo" },\r
+        { "vivo",     "video/vivo" },\r
+        { "vivo",     "video/vnd.vivo" },\r
+        { "vmd",      "application/vocaltec-media-desc" },\r
+        { "vmf",      "application/vocaltec-media-file" },\r
+        { "voc",      "audio/voc" },\r
+        { "voc",      "audio/x-voc" },\r
+        { "vos",      "video/vosaic" },\r
+        { "vox",      "audio/voxware" },\r
+        { "vqe",      "audio/x-twinvq-plugin" },\r
+        { "vqf",      "audio/x-twinvq" },\r
+        { "vql",      "audio/x-twinvq-plugin" },\r
+        { "vrml",     "application/x-vrml" },\r
+        { "vrml",     "model/vrml" },\r
+        { "vrml",     "x-world/x-vrml" },\r
+        { "vrt",      "x-world/x-vrt" },\r
+        { "vsd",      "application/x-visio" },\r
+        { "vst",      "application/x-visio" },\r
+        { "vsw",      "application/x-visio" },\r
+        { "w60",      "application/wordperfect6.0" },\r
+        { "w61",      "application/wordperfect6.1" },\r
+        { "w6w",      "application/msword" },\r
+        { "wav",      "audio/wav" },\r
+        { "wav",      "audio/x-wav" },\r
+        { "wb1",      "application/x-qpro" },\r
+        { "wbmp",     "image/vnd.wap.wbmp" },\r
+        { "web",      "application/vnd.xara" },\r
+        { "wiz",      "application/msword" },\r
+        { "wk1",      "application/x-123" },\r
+        { "wmf",      "windows/metafile" },\r
+        { "wml",      "text/vnd.wap.wml" },\r
+        { "wmlc",     "application/vnd.wap.wmlc" },\r
+        { "wmls",     "text/vnd.wap.wmlscript" },\r
+        { "wmlsc",    "application/vnd.wap.wmlscriptc" },\r
+        { "word",     "application/msword" },\r
+        { "wp",       "application/wordperfect" },\r
+        { "wp5",      "application/wordperfect" },\r
+        { "wp5",      "application/wordperfect6.0" },\r
+        { "wp6",      "application/wordperfect" },\r
+        { "wpd",      "application/wordperfect" },\r
+        { "wpd",      "application/x-wpwin" },\r
+        { "wq1",      "application/x-lotus" },\r
+        { "wri",      "application/mswrite" },\r
+        { "wri",      "application/x-wri" },\r
+        { "wrl",      "application/x-world" },\r
+        { "wrl",      "model/vrml" },\r
+        { "wrl",      "x-world/x-vrml" },\r
+        { "wrz",      "model/vrml" },\r
+        { "wrz",      "x-world/x-vrml" },\r
+        { "wsc",      "text/scriplet" },\r
+        { "wsrc",     "application/x-wais-source" },\r
+        { "wtk",      "application/x-wintalk" },\r
+        { "xbm",      "image/x-xbitmap" },\r
+        { "xbm",      "image/x-xbm" },\r
+        { "xbm",      "image/xbm" },\r
+        { "xdr",      "video/x-amt-demorun" },\r
+        { "xgz",      "xgl/drawing" },\r
+        { "xif",      "image/vnd.xiff" },\r
+        { "xl",       "application/excel" },\r
+        { "xla",      "application/excel" },\r
+        { "xla",      "application/x-excel" },\r
+        { "xla",      "application/x-msexcel" },\r
+        { "xlb",      "application/excel" },\r
+        { "xlb",      "application/vnd.ms-excel" },\r
+        { "xlb",      "application/x-excel" },\r
+        { "xlc",      "application/excel" },\r
+        { "xlc",      "application/vnd.ms-excel" },\r
+        { "xlc",      "application/x-excel" },\r
+        { "xld",      "application/excel" },\r
+        { "xld",      "application/x-excel" },\r
+        { "xlk",      "application/excel" },\r
+        { "xlk",      "application/x-excel" },\r
+        { "xll",      "application/excel" },\r
+        { "xll",      "application/vnd.ms-excel" },\r
+        { "xll",      "application/x-excel" },\r
+        { "xlm",      "application/excel" },\r
+        { "xlm",      "application/vnd.ms-excel" },\r
+        { "xlm",      "application/x-excel" },\r
+        { "xls",      "application/excel" },\r
+        { "xls",      "application/vnd.ms-excel" },\r
+        { "xls",      "application/x-excel" },\r
+        { "xls",      "application/x-msexcel" },\r
+        { "xlt",      "application/excel" },\r
+        { "xlt",      "application/x-excel" },\r
+        { "xlv",      "application/excel" },\r
+        { "xlv",      "application/x-excel" },\r
+        { "xlw",      "application/excel" },\r
+        { "xlw",      "application/vnd.ms-excel" },\r
+        { "xlw",      "application/x-excel" },\r
+        { "xlw",      "application/x-msexcel" },\r
+        { "xm",       "audio/xm" },\r
+        { "xml",      "application/xml" },\r
+        { "xml",      "text/xml" },\r
+        { "xmz",      "xgl/movie" },\r
+        { "xpix",     "application/x-vnd.ls-xpix" },\r
+        { "xpm",      "image/x-xpixmap" },\r
+        { "xpm",      "image/xpm" },\r
+        { "x-png",    "image/png" },\r
+        { "xsr",      "video/x-amt-showrun" },\r
+        { "xwd",      "image/x-xwd" },\r
+        { "xwd",      "image/x-xwindowdump" },\r
+        { "xyz",      "chemical/x-pdb" },\r
+        { "z",        "application/x-compress" },\r
+        { "z",        "application/x-compressed" },\r
+        { "zip",      "application/x-compressed" },\r
+        { "zip",      "application/x-zip-compressed" },\r
+        { "zip",      "application/zip" },\r
+        { "zip",      "multipart/x-zip" },\r
+        { "zoo",      "application/octet-stream" },\r
+    };\r
+\r
+    template <typename EntryToPair>\r
+    static std::multimap<String, String> createMultiMap (EntryToPair&& entryToPair)\r
+    {\r
+        std::pair<const char*, const char*> transformed[std::size (initialEntries)];\r
+        std::transform (std::begin (initialEntries),\r
+                        std::end   (initialEntries),\r
+                        std::begin (transformed),\r
+                        entryToPair);\r
 \r
-StringArray getMimeTypesForFileExtension (const String& fileExtension)\r
+        return { std::begin (transformed),\r
+                 std::end   (transformed) };\r
+    }\r
+\r
+    std::multimap<String, String> typeForExtension = createMultiMap ([] (auto e)\r
+    {\r
+        return std::make_pair (e.fileExtension, e.mimeType);\r
+    });\r
+\r
+    std::multimap<String, String> extensionForType = createMultiMap ([] (auto e)\r
+    {\r
+        return std::make_pair (e.mimeType, e.fileExtension);\r
+    });\r
+};\r
+\r
+} // namespace\r
+\r
+void MimeTypeTable::registerCustomMimeTypeForFileExtension (const String& mimeType, const String& fileExtension)\r
 {\r
-    return getMatches (fileExtension, &MimeTypeTableEntry::fileExtension, &MimeTypeTableEntry::mimeType);\r
+    Table::get().addEntry ({ fileExtension.toRawUTF8(), mimeType.toRawUTF8() });\r
 }\r
 \r
-StringArray getFileExtensionsForMimeType (const String& mimeType)\r
+StringArray MimeTypeTable::getMimeTypesForFileExtension (const String& fileExtension)\r
 {\r
-    return getMatches (mimeType, &MimeTypeTableEntry::mimeType, &MimeTypeTableEntry::fileExtension);\r
+    return Table::get().getTypesForExtension (fileExtension);\r
 }\r
 \r
-} // namespace MimeTypeTable\r
-\r
-//==============================================================================\r
-MimeTypeTableEntry MimeTypeTableEntry::table[641] =\r
+StringArray MimeTypeTable::getFileExtensionsForMimeType (const String& mimeType)\r
 {\r
-    {"3dm",      "x-world/x-3dmf"},\r
-    {"3dmf",     "x-world/x-3dmf"},\r
-    {"a",        "application/octet-stream"},\r
-    {"aab",      "application/x-authorware-bin"},\r
-    {"aam",      "application/x-authorware-map"},\r
-    {"aas",      "application/x-authorware-seg"},\r
-    {"abc",      "text/vnd.abc"},\r
-    {"acgi",     "text/html"},\r
-    {"afl",      "video/animaflex"},\r
-    {"ai",       "application/postscript"},\r
-    {"aif",      "audio/aiff"},\r
-    {"aif",      "audio/x-aiff"},\r
-    {"aifc",     "audio/aiff"},\r
-    {"aifc",     "audio/x-aiff"},\r
-    {"aiff",     "audio/aiff"},\r
-    {"aiff",     "audio/x-aiff"},\r
-    {"aim",      "application/x-aim"},\r
-    {"aip",      "text/x-audiosoft-intra"},\r
-    {"ani",      "application/x-navi-animation"},\r
-    {"aos",      "application/x-nokia-9000-communicator-add-on-software"},\r
-    {"aps",      "application/mime"},\r
-    {"arc",      "application/octet-stream"},\r
-    {"arj",      "application/arj"},\r
-    {"arj",      "application/octet-stream"},\r
-    {"art",      "image/x-jg"},\r
-    {"asf",      "video/x-ms-asf"},\r
-    {"asm",      "text/x-asm"},\r
-    {"asp",      "text/asp"},\r
-    {"asx",      "application/x-mplayer2"},\r
-    {"asx",      "video/x-ms-asf"},\r
-    {"asx",      "video/x-ms-asf-plugin"},\r
-    {"au",       "audio/basic"},\r
-    {"au",       "audio/x-au"},\r
-    {"avi",      "application/x-troff-msvideo"},\r
-    {"avi",      "video/avi"},\r
-    {"avi",      "video/msvideo"},\r
-    {"avi",      "video/x-msvideo"},\r
-    {"avs",      "video/avs-video"},\r
-    {"bcpio",    "application/x-bcpio"},\r
-    {"bin",      "application/mac-binary"},\r
-    {"bin",      "application/macbinary"},\r
-    {"bin",      "application/octet-stream"},\r
-    {"bin",      "application/x-binary"},\r
-    {"bin",      "application/x-macbinary"},\r
-    {"bm",       "image/bmp"},\r
-    {"bmp",      "image/bmp"},\r
-    {"bmp",      "image/x-windows-bmp"},\r
-    {"boo",      "application/book"},\r
-    {"book",     "application/book"},\r
-    {"boz",      "application/x-bzip2"},\r
-    {"bsh",      "application/x-bsh"},\r
-    {"bz",       "application/x-bzip"},\r
-    {"bz2",      "application/x-bzip2"},\r
-    {"c",        "text/plain"},\r
-    {"c",        "text/x-c"},\r
-    {"c++",      "text/plain"},\r
-    {"cat",      "application/vnd.ms-pki.seccat"},\r
-    {"cc",       "text/plain"},\r
-    {"cc",       "text/x-c"},\r
-    {"ccad",     "application/clariscad"},\r
-    {"cco",      "application/x-cocoa"},\r
-    {"cdf",      "application/cdf"},\r
-    {"cdf",      "application/x-cdf"},\r
-    {"cdf",      "application/x-netcdf"},\r
-    {"cer",      "application/pkix-cert"},\r
-    {"cer",      "application/x-x509-ca-cert"},\r
-    {"cha",      "application/x-chat"},\r
-    {"chat",     "application/x-chat"},\r
-    {"class",    "application/java"},\r
-    {"class",    "application/java-byte-code"},\r
-    {"class",    "application/x-java-class"},\r
-    {"com",      "application/octet-stream"},\r
-    {"com",      "text/plain"},\r
-    {"conf",     "text/plain"},\r
-    {"cpio",     "application/x-cpio"},\r
-    {"cpp",      "text/x-c"},\r
-    {"cpt",      "application/mac-compactpro"},\r
-    {"cpt",      "application/x-compactpro"},\r
-    {"cpt",      "application/x-cpt"},\r
-    {"crl",      "application/pkcs-crl"},\r
-    {"crl",      "application/pkix-crl"},\r
-    {"crt",      "application/pkix-cert"},\r
-    {"crt",      "application/x-x509-ca-cert"},\r
-    {"crt",      "application/x-x509-user-cert"},\r
-    {"csh",      "application/x-csh"},\r
-    {"csh",      "text/x-script.csh"},\r
-    {"css",      "application/x-pointplus"},\r
-    {"css",      "text/css"},\r
-    {"cxx",      "text/plain"},\r
-    {"dcr",      "application/x-director"},\r
-    {"deepv",    "application/x-deepv"},\r
-    {"def",      "text/plain"},\r
-    {"der",      "application/x-x509-ca-cert"},\r
-    {"dif",      "video/x-dv"},\r
-    {"dir",      "application/x-director"},\r
-    {"dl",       "video/dl"},\r
-    {"dl",       "video/x-dl"},\r
-    {"doc",      "application/msword"},\r
-    {"dot",      "application/msword"},\r
-    {"dp",       "application/commonground"},\r
-    {"drw",      "application/drafting"},\r
-    {"dump",     "application/octet-stream"},\r
-    {"dv",       "video/x-dv"},\r
-    {"dvi",      "application/x-dvi"},\r
-    {"dwf",      "drawing/x-dwf"},\r
-    {"dwf",      "model/vnd.dwf"},\r
-    {"dwg",      "application/acad"},\r
-    {"dwg",      "image/vnd.dwg"},\r
-    {"dwg",      "image/x-dwg"},\r
-    {"dxf",      "application/dxf"},\r
-    {"dxf",      "image/vnd.dwg"},\r
-    {"dxf",      "image/x-dwg"},\r
-    {"dxr",      "application/x-director"},\r
-    {"el",       "text/x-script.elisp"},\r
-    {"elc",      "application/x-bytecode.elisp"},\r
-    {"elc",      "application/x-elc"},\r
-    {"env",      "application/x-envoy"},\r
-    {"eps",      "application/postscript"},\r
-    {"es",       "application/x-esrehber"},\r
-    {"etx",      "text/x-setext"},\r
-    {"evy",      "application/envoy"},\r
-    {"evy",      "application/x-envoy"},\r
-    {"exe",      "application/octet-stream"},\r
-    {"f",        "text/plain"},\r
-    {"f",        "text/x-fortran"},\r
-    {"f77",      "text/x-fortran"},\r
-    {"f90",      "text/plain"},\r
-    {"f90",      "text/x-fortran"},\r
-    {"fdf",      "application/vnd.fdf"},\r
-    {"fif",      "application/fractals"},\r
-    {"fif",      "image/fif"},\r
-    {"fli",      "video/fli"},\r
-    {"fli",      "video/x-fli"},\r
-    {"flo",      "image/florian"},\r
-    {"flx",      "text/vnd.fmi.flexstor"},\r
-    {"fmf",      "video/x-atomic3d-feature"},\r
-    {"for",      "text/plain"},\r
-    {"for",      "text/x-fortran"},\r
-    {"fpx",      "image/vnd.fpx"},\r
-    {"fpx",      "image/vnd.net-fpx"},\r
-    {"frl",      "application/freeloader"},\r
-    {"funk",     "audio/make"},\r
-    {"g",        "text/plain"},\r
-    {"g3",       "image/g3fax"},\r
-    {"gif",      "image/gif"},\r
-    {"gl",       "video/gl"},\r
-    {"gl",       "video/x-gl"},\r
-    {"gsd",      "audio/x-gsm"},\r
-    {"gsm",      "audio/x-gsm"},\r
-    {"gsp",      "application/x-gsp"},\r
-    {"gss",      "application/x-gss"},\r
-    {"gtar",     "application/x-gtar"},\r
-    {"gz",       "application/x-compressed"},\r
-    {"gz",       "application/x-gzip"},\r
-    {"gzip",     "application/x-gzip"},\r
-    {"gzip",     "multipart/x-gzip"},\r
-    {"h",        "text/plain"},\r
-    {"h",        "text/x-h"},\r
-    {"hdf",      "application/x-hdf"},\r
-    {"help",     "application/x-helpfile"},\r
-    {"hgl",      "application/vnd.hp-hpgl"},\r
-    {"hh",       "text/plain"},\r
-    {"hh",       "text/x-h"},\r
-    {"hlb",      "text/x-script"},\r
-    {"hlp",      "application/hlp"},\r
-    {"hlp",      "application/x-helpfile"},\r
-    {"hlp",      "application/x-winhelp"},\r
-    {"hpg",      "application/vnd.hp-hpgl"},\r
-    {"hpgl",     "application/vnd.hp-hpgl"},\r
-    {"hqx",      "application/binhex"},\r
-    {"hqx",      "application/binhex4"},\r
-    {"hqx",      "application/mac-binhex"},\r
-    {"hqx",      "application/mac-binhex40"},\r
-    {"hqx",      "application/x-binhex40"},\r
-    {"hqx",      "application/x-mac-binhex40"},\r
-    {"hta",      "application/hta"},\r
-    {"htc",      "text/x-component"},\r
-    {"htm",      "text/html"},\r
-    {"html",     "text/html"},\r
-    {"htmls",    "text/html"},\r
-    {"htt",      "text/webviewhtml"},\r
-    {"htx",      "text/html"},\r
-    {"ice",      "x-conference/x-cooltalk"},\r
-    {"ico",      "image/x-icon"},\r
-    {"idc",      "text/plain"},\r
-    {"ief",      "image/ief"},\r
-    {"iefs",     "image/ief"},\r
-    {"iges",     "application/iges"},\r
-    {"iges",     "model/iges"},\r
-    {"igs",      "application/iges"},\r
-    {"igs",      "model/iges"},\r
-    {"ima",      "application/x-ima"},\r
-    {"imap",     "application/x-httpd-imap"},\r
-    {"inf",      "application/inf"},\r
-    {"ins",      "application/x-internett-signup"},\r
-    {"ip",       "application/x-ip2"},\r
-    {"isu",      "video/x-isvideo"},\r
-    {"it",       "audio/it"},\r
-    {"iv",       "application/x-inventor"},\r
-    {"ivr",      "i-world/i-vrml"},\r
-    {"ivy",      "application/x-livescreen"},\r
-    {"jam",      "audio/x-jam"},\r
-    {"jav",      "text/plain"},\r
-    {"jav",      "text/x-java-source"},\r
-    {"java",     "text/plain"},\r
-    {"java",     "text/x-java-source"},\r
-    {"jcm",      "application/x-java-commerce"},\r
-    {"jfif",     "image/jpeg"},\r
-    {"jfif",     "image/pjpeg"},\r
-    {"jpe",      "image/jpeg"},\r
-    {"jpe",      "image/pjpeg"},\r
-    {"jpeg",     "image/jpeg"},\r
-    {"jpeg",     "image/pjpeg"},\r
-    {"jpg",      "image/jpeg"},\r
-    {"jpg",      "image/pjpeg"},\r
-    {"jps",      "image/x-jps"},\r
-    {"js",       "application/x-javascript"},\r
-    {"jut",      "image/jutvision"},\r
-    {"kar",      "audio/midi"},\r
-    {"kar",      "music/x-karaoke"},\r
-    {"ksh",      "application/x-ksh"},\r
-    {"ksh",      "text/x-script.ksh"},\r
-    {"la",       "audio/nspaudio"},\r
-    {"la",       "audio/x-nspaudio"},\r
-    {"lam",      "audio/x-liveaudio"},\r
-    {"latex",    "application/x-latex"},\r
-    {"lha",      "application/lha"},\r
-    {"lha",      "application/octet-stream"},\r
-    {"lha",      "application/x-lha"},\r
-    {"lhx",      "application/octet-stream"},\r
-    {"list",     "text/plain"},\r
-    {"lma",      "audio/nspaudio"},\r
-    {"lma",      "audio/x-nspaudio"},\r
-    {"log",      "text/plain"},\r
-    {"lsp",      "application/x-lisp"},\r
-    {"lsp",      "text/x-script.lisp"},\r
-    {"lst",      "text/plain"},\r
-    {"lsx",      "text/x-la-asf"},\r
-    {"ltx",      "application/x-latex"},\r
-    {"lzh",      "application/octet-stream"},\r
-    {"lzh",      "application/x-lzh"},\r
-    {"lzx",      "application/lzx"},\r
-    {"lzx",      "application/octet-stream"},\r
-    {"lzx",      "application/x-lzx"},\r
-    {"m",        "text/plain"},\r
-    {"m",        "text/x-m"},\r
-    {"m1v",      "video/mpeg"},\r
-    {"m2a",      "audio/mpeg"},\r
-    {"m2v",      "video/mpeg"},\r
-    {"m3u",      "audio/x-mpequrl"},\r
-    {"man",      "application/x-troff-man"},\r
-    {"map",      "application/x-navimap"},\r
-    {"mar",      "text/plain"},\r
-    {"mbd",      "application/mbedlet"},\r
-    {"mc$",      "application/x-magic-cap-package-1.0"},\r
-    {"mcd",      "application/mcad"},\r
-    {"mcd",      "application/x-mathcad"},\r
-    {"mcf",      "image/vasa"},\r
-    {"mcf",      "text/mcf"},\r
-    {"mcp",      "application/netmc"},\r
-    {"me",       "application/x-troff-me"},\r
-    {"mht",      "message/rfc822"},\r
-    {"mhtml",    "message/rfc822"},\r
-    {"mid",      "application/x-midi"},\r
-    {"mid",      "audio/midi"},\r
-    {"mid",      "audio/x-mid"},\r
-    {"mid",      "audio/x-midi"},\r
-    {"mid",      "music/crescendo"},\r
-    {"mid",      "x-music/x-midi"},\r
-    {"midi",     "application/x-midi"},\r
-    {"midi",     "audio/midi"},\r
-    {"midi",     "audio/x-mid"},\r
-    {"midi",     "audio/x-midi"},\r
-    {"midi",     "music/crescendo"},\r
-    {"midi",     "x-music/x-midi"},\r
-    {"mif",      "application/x-frame"},\r
-    {"mif",      "application/x-mif"},\r
-    {"mime",     "message/rfc822"},\r
-    {"mime",     "www/mime"},\r
-    {"mjf",      "audio/x-vnd.audioexplosion.mjuicemediafile"},\r
-    {"mjpg",     "video/x-motion-jpeg"},\r
-    {"mm",       "application/base64"},\r
-    {"mm",       "application/x-meme"},\r
-    {"mme",      "application/base64"},\r
-    {"mod",      "audio/mod"},\r
-    {"mod",      "audio/x-mod"},\r
-    {"moov",     "video/quicktime"},\r
-    {"mov",      "video/quicktime"},\r
-    {"movie",    "video/x-sgi-movie"},\r
-    {"mp2",      "audio/mpeg"},\r
-    {"mp2",      "audio/x-mpeg"},\r
-    {"mp2",      "video/mpeg"},\r
-    {"mp2",      "video/x-mpeg"},\r
-    {"mp2",      "video/x-mpeq2a"},\r
-    {"mp3",      "audio/mpeg"},\r
-    {"mp3",      "audio/mpeg3"},\r
-    {"mp3",      "audio/x-mpeg-3"},\r
-    {"mp3",      "video/mpeg"},\r
-    {"mp3",      "video/x-mpeg"},\r
-    {"mpa",      "audio/mpeg"},\r
-    {"mpa",      "video/mpeg"},\r
-    {"mpc",      "application/x-project"},\r
-    {"mpe",      "video/mpeg"},\r
-    {"mpeg",     "video/mpeg"},\r
-    {"mpg",      "audio/mpeg"},\r
-    {"mpg",      "video/mpeg"},\r
-    {"mpga",     "audio/mpeg"},\r
-    {"mpp",      "application/vnd.ms-project"},\r
-    {"mpt",      "application/x-project"},\r
-    {"mpv",      "application/x-project"},\r
-    {"mpx",      "application/x-project"},\r
-    {"mrc",      "application/marc"},\r
-    {"ms",       "application/x-troff-ms"},\r
-    {"mv",       "video/x-sgi-movie"},\r
-    {"my",       "audio/make"},\r
-    {"mzz",      "application/x-vnd.audioexplosion.mzz"},\r
-    {"nap",      "image/naplps"},\r
-    {"naplps",   "image/naplps"},\r
-    {"nc",       "application/x-netcdf"},\r
-    {"ncm",      "application/vnd.nokia.configuration-message"},\r
-    {"nif",      "image/x-niff"},\r
-    {"niff",     "image/x-niff"},\r
-    {"nix",      "application/x-mix-transfer"},\r
-    {"nsc",      "application/x-conference"},\r
-    {"nvd",      "application/x-navidoc"},\r
-    {"o",        "application/octet-stream"},\r
-    {"oda",      "application/oda"},\r
-    {"omc",      "application/x-omc"},\r
-    {"omcd",     "application/x-omcdatamaker"},\r
-    {"omcr",     "application/x-omcregerator"},\r
-    {"p",        "text/x-pascal"},\r
-    {"p10",      "application/pkcs10"},\r
-    {"p10",      "application/x-pkcs10"},\r
-    {"p12",      "application/pkcs-12"},\r
-    {"p12",      "application/x-pkcs12"},\r
-    {"p7a",      "application/x-pkcs7-signature"},\r
-    {"p7c",      "application/pkcs7-mime"},\r
-    {"p7c",      "application/x-pkcs7-mime"},\r
-    {"p7m",      "application/pkcs7-mime"},\r
-    {"p7m",      "application/x-pkcs7-mime"},\r
-    {"p7r",      "application/x-pkcs7-certreqresp"},\r
-    {"p7s",      "application/pkcs7-signature"},\r
-    {"part",     "application/pro_eng"},\r
-    {"pas",      "text/pascal"},\r
-    {"pbm",      "image/x-portable-bitmap"},\r
-    {"pcl",      "application/vnd.hp-pcl"},\r
-    {"pcl",      "application/x-pcl"},\r
-    {"pct",      "image/x-pict"},\r
-    {"pcx",      "image/x-pcx"},\r
-    {"pdb",      "chemical/x-pdb"},\r
-    {"pdf",      "application/pdf"},\r
-    {"pfunk",    "audio/make"},\r
-    {"pfunk",    "audio/make.my.funk"},\r
-    {"pgm",      "image/x-portable-graymap"},\r
-    {"pgm",      "image/x-portable-greymap"},\r
-    {"pic",      "image/pict"},\r
-    {"pict",     "image/pict"},\r
-    {"pkg",      "application/x-newton-compatible-pkg"},\r
-    {"pko",      "application/vnd.ms-pki.pko"},\r
-    {"pl",       "text/plain"},\r
-    {"pl",       "text/x-script.perl"},\r
-    {"plx",      "application/x-pixclscript"},\r
-    {"pm",       "image/x-xpixmap"},\r
-    {"pm",       "text/x-script.perl-module"},\r
-    {"pm4",      "application/x-pagemaker"},\r
-    {"pm5",      "application/x-pagemaker"},\r
-    {"png",      "image/png"},\r
-    {"pnm",      "application/x-portable-anymap"},\r
-    {"pnm",      "image/x-portable-anymap"},\r
-    {"pot",      "application/mspowerpoint"},\r
-    {"pot",      "application/vnd.ms-powerpoint"},\r
-    {"pov",      "model/x-pov"},\r
-    {"ppa",      "application/vnd.ms-powerpoint"},\r
-    {"ppm",      "image/x-portable-pixmap"},\r
-    {"pps",      "application/mspowerpoint"},\r
-    {"pps",      "application/vnd.ms-powerpoint"},\r
-    {"ppt",      "application/mspowerpoint"},\r
-    {"ppt",      "application/powerpoint"},\r
-    {"ppt",      "application/vnd.ms-powerpoint"},\r
-    {"ppt",      "application/x-mspowerpoint"},\r
-    {"ppz",      "application/mspowerpoint"},\r
-    {"pre",      "application/x-freelance"},\r
-    {"prt",      "application/pro_eng"},\r
-    {"ps",       "application/postscript"},\r
-    {"psd",      "application/octet-stream"},\r
-    {"pvu",      "paleovu/x-pv"},\r
-    {"pwz",      "application/vnd.ms-powerpoint"},\r
-    {"py",       "text/x-script.python"},\r
-    {"pyc",      "application/x-bytecode.python"},\r
-    {"qcp",      "audio/vnd.qcelp"},\r
-    {"qd3",      "x-world/x-3dmf"},\r
-    {"qd3d",     "x-world/x-3dmf"},\r
-    {"qif",      "image/x-quicktime"},\r
-    {"qt",       "video/quicktime"},\r
-    {"qtc",      "video/x-qtc"},\r
-    {"qti",      "image/x-quicktime"},\r
-    {"qtif",     "image/x-quicktime"},\r
-    {"ra",       "audio/x-pn-realaudio"},\r
-    {"ra",       "audio/x-pn-realaudio-plugin"},\r
-    {"ra",       "audio/x-realaudio"},\r
-    {"ram",      "audio/x-pn-realaudio"},\r
-    {"ras",      "application/x-cmu-raster"},\r
-    {"ras",      "image/cmu-raster"},\r
-    {"ras",      "image/x-cmu-raster"},\r
-    {"rast",     "image/cmu-raster"},\r
-    {"rexx",     "text/x-script.rexx"},\r
-    {"rf",       "image/vnd.rn-realflash"},\r
-    {"rgb",      "image/x-rgb"},\r
-    {"rm",       "application/vnd.rn-realmedia"},\r
-    {"rm",       "audio/x-pn-realaudio"},\r
-    {"rmi",      "audio/mid"},\r
-    {"rmm",      "audio/x-pn-realaudio"},\r
-    {"rmp",      "audio/x-pn-realaudio"},\r
-    {"rmp",      "audio/x-pn-realaudio-plugin"},\r
-    {"rng",      "application/ringing-tones"},\r
-    {"rng",      "application/vnd.nokia.ringing-tone"},\r
-    {"rnx",      "application/vnd.rn-realplayer"},\r
-    {"roff",     "application/x-troff"},\r
-    {"rp",       "image/vnd.rn-realpix"},\r
-    {"rpm",      "audio/x-pn-realaudio-plugin"},\r
-    {"rt",       "text/richtext"},\r
-    {"rt",       "text/vnd.rn-realtext"},\r
-    {"rtf",      "application/rtf"},\r
-    {"rtf",      "application/x-rtf"},\r
-    {"rtf",      "text/richtext"},\r
-    {"rtx",      "application/rtf"},\r
-    {"rtx",      "text/richtext"},\r
-    {"rv",       "video/vnd.rn-realvideo"},\r
-    {"s",        "text/x-asm"},\r
-    {"s3m",      "audio/s3m"},\r
-    {"saveme",   "application/octet-stream"},\r
-    {"sbk",      "application/x-tbook"},\r
-    {"scm",      "application/x-lotusscreencam"},\r
-    {"scm",      "text/x-script.guile"},\r
-    {"scm",      "text/x-script.scheme"},\r
-    {"scm",      "video/x-scm"},\r
-    {"sdml",     "text/plain"},\r
-    {"sdp",      "application/sdp"},\r
-    {"sdp",      "application/x-sdp"},\r
-    {"sdr",      "application/sounder"},\r
-    {"sea",      "application/sea"},\r
-    {"sea",      "application/x-sea"},\r
-    {"set",      "application/set"},\r
-    {"sgm",      "text/sgml"},\r
-    {"sgm",      "text/x-sgml"},\r
-    {"sgml",     "text/sgml"},\r
-    {"sgml",     "text/x-sgml"},\r
-    {"sh",       "application/x-bsh"},\r
-    {"sh",       "application/x-sh"},\r
-    {"sh",       "application/x-shar"},\r
-    {"sh",       "text/x-script.sh"},\r
-    {"shar",     "application/x-bsh"},\r
-    {"shar",     "application/x-shar"},\r
-    {"shtml",    "text/html"},\r
-    {"shtml",    "text/x-server-parsed-html"},\r
-    {"sid",      "audio/x-psid"},\r
-    {"sit",      "application/x-sit"},\r
-    {"sit",      "application/x-stuffit"},\r
-    {"skd",      "application/x-koan"},\r
-    {"skm",      "application/x-koan"},\r
-    {"skp",      "application/x-koan"},\r
-    {"skt",      "application/x-koan"},\r
-    {"sl",       "application/x-seelogo"},\r
-    {"smi",      "application/smil"},\r
-    {"smil",     "application/smil"},\r
-    {"snd",      "audio/basic"},\r
-    {"snd",      "audio/x-adpcm"},\r
-    {"sol",      "application/solids"},\r
-    {"spc",      "application/x-pkcs7-certificates"},\r
-    {"spc",      "text/x-speech"},\r
-    {"spl",      "application/futuresplash"},\r
-    {"spr",      "application/x-sprite"},\r
-    {"sprite",   "application/x-sprite"},\r
-    {"src",      "application/x-wais-source"},\r
-    {"ssi",      "text/x-server-parsed-html"},\r
-    {"ssm",      "application/streamingmedia"},\r
-    {"sst",      "application/vnd.ms-pki.certstore"},\r
-    {"step",     "application/step"},\r
-    {"stl",      "application/sla"},\r
-    {"stl",      "application/vnd.ms-pki.stl"},\r
-    {"stl",      "application/x-navistyle"},\r
-    {"stp",      "application/step"},\r
-    {"sv4cpio,", "application/x-sv4cpio"},\r
-    {"sv4crc",   "application/x-sv4crc"},\r
-    {"svf",      "image/vnd.dwg"},\r
-    {"svf",      "image/x-dwg"},\r
-    {"svr",      "application/x-world"},\r
-    {"svr",      "x-world/x-svr"},\r
-    {"swf",      "application/x-shockwave-flash"},\r
-    {"t",        "application/x-troff"},\r
-    {"talk",     "text/x-speech"},\r
-    {"tar",      "application/x-tar"},\r
-    {"tbk",      "application/toolbook"},\r
-    {"tbk",      "application/x-tbook"},\r
-    {"tcl",      "application/x-tcl"},\r
-    {"tcl",      "text/x-script.tcl"},\r
-    {"tcsh",     "text/x-script.tcsh"},\r
-    {"tex",      "application/x-tex"},\r
-    {"texi",     "application/x-texinfo"},\r
-    {"texinfo,", "application/x-texinfo"},\r
-    {"text",     "application/plain"},\r
-    {"text",     "text/plain"},\r
-    {"tgz",      "application/gnutar"},\r
-    {"tgz",      "application/x-compressed"},\r
-    {"tif",      "image/tiff"},\r
-    {"tif",      "image/x-tiff"},\r
-    {"tiff",     "image/tiff"},\r
-    {"tiff",     "image/x-tiff"},\r
-    {"tr",       "application/x-troff"},\r
-    {"tsi",      "audio/tsp-audio"},\r
-    {"tsp",      "application/dsptype"},\r
-    {"tsp",      "audio/tsplayer"},\r
-    {"tsv",      "text/tab-separated-values"},\r
-    {"turbot",   "image/florian"},\r
-    {"txt",      "text/plain"},\r
-    {"uil",      "text/x-uil"},\r
-    {"uni",      "text/uri-list"},\r
-    {"unis",     "text/uri-list"},\r
-    {"unv",      "application/i-deas"},\r
-    {"uri",      "text/uri-list"},\r
-    {"uris",     "text/uri-list"},\r
-    {"ustar",    "application/x-ustar"},\r
-    {"ustar",    "multipart/x-ustar"},\r
-    {"uu",       "application/octet-stream"},\r
-    {"uu",       "text/x-uuencode"},\r
-    {"uue",      "text/x-uuencode"},\r
-    {"vcd",      "application/x-cdlink"},\r
-    {"vcs",      "text/x-vcalendar"},\r
-    {"vda",      "application/vda"},\r
-    {"vdo",      "video/vdo"},\r
-    {"vew",      "application/groupwise"},\r
-    {"viv",      "video/vivo"},\r
-    {"viv",      "video/vnd.vivo"},\r
-    {"vivo",     "video/vivo"},\r
-    {"vivo",     "video/vnd.vivo"},\r
-    {"vmd",      "application/vocaltec-media-desc"},\r
-    {"vmf",      "application/vocaltec-media-file"},\r
-    {"voc",      "audio/voc"},\r
-    {"voc",      "audio/x-voc"},\r
-    {"vos",      "video/vosaic"},\r
-    {"vox",      "audio/voxware"},\r
-    {"vqe",      "audio/x-twinvq-plugin"},\r
-    {"vqf",      "audio/x-twinvq"},\r
-    {"vql",      "audio/x-twinvq-plugin"},\r
-    {"vrml",     "application/x-vrml"},\r
-    {"vrml",     "model/vrml"},\r
-    {"vrml",     "x-world/x-vrml"},\r
-    {"vrt",      "x-world/x-vrt"},\r
-    {"vsd",      "application/x-visio"},\r
-    {"vst",      "application/x-visio"},\r
-    {"vsw",      "application/x-visio"},\r
-    {"w60",      "application/wordperfect6.0"},\r
-    {"w61",      "application/wordperfect6.1"},\r
-    {"w6w",      "application/msword"},\r
-    {"wav",      "audio/wav"},\r
-    {"wav",      "audio/x-wav"},\r
-    {"wb1",      "application/x-qpro"},\r
-    {"wbmp",     "image/vnd.wap.wbmp"},\r
-    {"web",      "application/vnd.xara"},\r
-    {"wiz",      "application/msword"},\r
-    {"wk1",      "application/x-123"},\r
-    {"wmf",      "windows/metafile"},\r
-    {"wml",      "text/vnd.wap.wml"},\r
-    {"wmlc",     "application/vnd.wap.wmlc"},\r
-    {"wmls",     "text/vnd.wap.wmlscript"},\r
-    {"wmlsc",    "application/vnd.wap.wmlscriptc"},\r
-    {"word",     "application/msword"},\r
-    {"wp",       "application/wordperfect"},\r
-    {"wp5",      "application/wordperfect"},\r
-    {"wp5",      "application/wordperfect6.0"},\r
-    {"wp6",      "application/wordperfect"},\r
-    {"wpd",      "application/wordperfect"},\r
-    {"wpd",      "application/x-wpwin"},\r
-    {"wq1",      "application/x-lotus"},\r
-    {"wri",      "application/mswrite"},\r
-    {"wri",      "application/x-wri"},\r
-    {"wrl",      "application/x-world"},\r
-    {"wrl",      "model/vrml"},\r
-    {"wrl",      "x-world/x-vrml"},\r
-    {"wrz",      "model/vrml"},\r
-    {"wrz",      "x-world/x-vrml"},\r
-    {"wsc",      "text/scriplet"},\r
-    {"wsrc",     "application/x-wais-source"},\r
-    {"wtk",      "application/x-wintalk"},\r
-    {"xbm",      "image/x-xbitmap"},\r
-    {"xbm",      "image/x-xbm"},\r
-    {"xbm",      "image/xbm"},\r
-    {"xdr",      "video/x-amt-demorun"},\r
-    {"xgz",      "xgl/drawing"},\r
-    {"xif",      "image/vnd.xiff"},\r
-    {"xl",       "application/excel"},\r
-    {"xla",      "application/excel"},\r
-    {"xla",      "application/x-excel"},\r
-    {"xla",      "application/x-msexcel"},\r
-    {"xlb",      "application/excel"},\r
-    {"xlb",      "application/vnd.ms-excel"},\r
-    {"xlb",      "application/x-excel"},\r
-    {"xlc",      "application/excel"},\r
-    {"xlc",      "application/vnd.ms-excel"},\r
-    {"xlc",      "application/x-excel"},\r
-    {"xld",      "application/excel"},\r
-    {"xld",      "application/x-excel"},\r
-    {"xlk",      "application/excel"},\r
-    {"xlk",      "application/x-excel"},\r
-    {"xll",      "application/excel"},\r
-    {"xll",      "application/vnd.ms-excel"},\r
-    {"xll",      "application/x-excel"},\r
-    {"xlm",      "application/excel"},\r
-    {"xlm",      "application/vnd.ms-excel"},\r
-    {"xlm",      "application/x-excel"},\r
-    {"xls",      "application/excel"},\r
-    {"xls",      "application/vnd.ms-excel"},\r
-    {"xls",      "application/x-excel"},\r
-    {"xls",      "application/x-msexcel"},\r
-    {"xlt",      "application/excel"},\r
-    {"xlt",      "application/x-excel"},\r
-    {"xlv",      "application/excel"},\r
-    {"xlv",      "application/x-excel"},\r
-    {"xlw",      "application/excel"},\r
-    {"xlw",      "application/vnd.ms-excel"},\r
-    {"xlw",      "application/x-excel"},\r
-    {"xlw",      "application/x-msexcel"},\r
-    {"xm",       "audio/xm"},\r
-    {"xml",      "application/xml"},\r
-    {"xml",      "text/xml"},\r
-    {"xmz",      "xgl/movie"},\r
-    {"xpix",     "application/x-vnd.ls-xpix"},\r
-    {"xpm",      "image/x-xpixmap"},\r
-    {"xpm",      "image/xpm"},\r
-    {"x-png",    "image/png"},\r
-    {"xsr",      "video/x-amt-showrun"},\r
-    {"xwd",      "image/x-xwd"},\r
-    {"xwd",      "image/x-xwindowdump"},\r
-    {"xyz",      "chemical/x-pdb"},\r
-    {"z",        "application/x-compress"},\r
-    {"z",        "application/x-compressed"},\r
-    {"zip",      "application/x-compressed"},\r
-    {"zip",      "application/x-zip-compressed"},\r
-    {"zip",      "application/zip"},\r
-    {"zip",      "multipart/x-zip"},\r
-    {"zoo",      "application/octet-stream"}\r
-};\r
+    return Table::get().getExtensionsForType (mimeType);\r
+}\r
 \r
 } // namespace juce\r
index 1d79b41bd88b6d880c560bbf2763d3098f428188..d3b3e7be9c9c4206bc7272d1caf00d4453e1b84f 100644 (file)
 namespace juce\r
 {\r
 \r
-namespace MimeTypeTable\r
+struct MimeTypeTable\r
 {\r
 \r
 /*  @internal */\r
-StringArray getMimeTypesForFileExtension (const String& fileExtension);\r
+static void registerCustomMimeTypeForFileExtension (const String& mimeType, const String& fileExtension);\r
 \r
 /*  @internal */\r
-StringArray getFileExtensionsForMimeType (const String& mimeType);\r
+static StringArray getMimeTypesForFileExtension (const String& fileExtension);\r
 \r
-} // namespace MimeTypeTable\r
+/*  @internal */\r
+static StringArray getFileExtensionsForMimeType (const String& mimeType);\r
+\r
+};\r
 \r
 } // namespace juce\r
index 3ad6c7754ac7a66804358c92714b8c41760f8e98..1582571c145d122d6c0eb5137f736b804fb20c99 100644 (file)
@@ -1278,7 +1278,7 @@ struct JavascriptEngine::RootObject   : public DynamicObject
         Expression* parseFunctionCall (FunctionCall* call, ExpPtr& function)\r
         {\r
             std::unique_ptr<FunctionCall> s (call);\r
-            s->object.reset (function.release());\r
+            s->object = std::move (function);\r
             match (TokenTypes::openParen);\r
 \r
             while (currentType != TokenTypes::closeParen)\r
@@ -1304,7 +1304,7 @@ struct JavascriptEngine::RootObject   : public DynamicObject
             if (matchIf (TokenTypes::openBracket))\r
             {\r
                 std::unique_ptr<ArraySubscript> s (new ArraySubscript (location));\r
-                s->object.reset (input.release());\r
+                s->object = std::move (input);\r
                 s->index.reset (parseExpression());\r
                 match (TokenTypes::closeBracket);\r
                 return parseSuffixes (s.release());\r
@@ -1513,7 +1513,7 @@ struct JavascriptEngine::RootObject   : public DynamicObject
         Expression* parseTernaryOperator (ExpPtr& condition)\r
         {\r
             std::unique_ptr<ConditionalOp> e (new ConditionalOp (location));\r
-            e->condition.reset (condition.release());\r
+            e->condition = std::move (condition);\r
             e->trueBranch.reset (parseExpression());\r
             match (TokenTypes::colon);\r
             e->falseBranch.reset (parseExpression());\r
@@ -1539,9 +1539,9 @@ struct JavascriptEngine::RootObject   : public DynamicObject
             setMethod ("clone", cloneFn);\r
         }\r
 \r
-        static Identifier getClassName()   { static const Identifier i ("Object"); return i; }\r
-        static var dump  (Args a)          { DBG (JSON::toString (a.thisObject)); ignoreUnused (a); return var::undefined(); }\r
-        static var cloneFn (Args a)        { return a.thisObject.clone(); }\r
+        static Identifier getClassName()            { static const Identifier i ("Object"); return i; }\r
+        static var dump  ([[maybe_unused]] Args a)  { DBG (JSON::toString (a.thisObject)); return var::undefined(); }\r
+        static var cloneFn (Args a)                 { return a.thisObject.clone(); }\r
     };\r
 \r
     //==============================================================================\r
index e79c1c91f40756cbbf0952f2ad7bc9f99865a514..99884b30bd2aa1263d1ca936101c3baa16b493b1 100644 (file)
 #include "zip/juce_ZipFile.cpp"\r
 #include "files/juce_FileFilter.cpp"\r
 #include "files/juce_WildcardFileFilter.cpp"\r
+#include "native/juce_native_ThreadPriorities.h"\r
 \r
 //==============================================================================\r
 #if ! JUCE_WINDOWS\r
index 1aafb16f06ce2ccb7da7d2d5854944f8ba65ca3c..4ce05eb81316062968013864360120d1432c37e3 100644 (file)
 \r
   ID:                 juce_core\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE core classes\r
   description:        The essential set of basic JUCE classes, as required by all the other JUCE modules. Includes text, container, memory, threading and i/o functionality.\r
   website:            http://www.juce.com/juce\r
   license:            ISC\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:\r
   OSXFrameworks:      Cocoa Foundation IOKit\r
index 226ddccc5fa4b84b05fcd0237198a68cc99c67ef..fd780c8876acea069a37f6bb314444c4ac31b966 100644 (file)
@@ -258,7 +258,7 @@ uint32 BigInteger::getBitRangeAsInt (const int startBit, int numBits) const noex
     return n & (((uint32) 0xffffffff) >> endSpace);\r
 }\r
 \r
-void BigInteger::setBitRangeAsInt (const int startBit, int numBits, uint32 valueToSet)\r
+BigInteger& BigInteger::setBitRangeAsInt (const int startBit, int numBits, uint32 valueToSet)\r
 {\r
     if (numBits > 32)\r
     {\r
@@ -271,10 +271,12 @@ void BigInteger::setBitRangeAsInt (const int startBit, int numBits, uint32 value
         setBit (startBit + i, (valueToSet & 1) != 0);\r
         valueToSet >>= 1;\r
     }\r
+\r
+    return *this;\r
 }\r
 \r
 //==============================================================================\r
-void BigInteger::clear() noexcept\r
+BigInteger& BigInteger::clear() noexcept\r
 {\r
     heapAllocation.free();\r
     allocatedSize = numPreallocatedInts;\r
@@ -283,9 +285,11 @@ void BigInteger::clear() noexcept
 \r
     for (int i = 0; i < numPreallocatedInts; ++i)\r
         preallocated[i] = 0;\r
+\r
+    return *this;\r
 }\r
 \r
-void BigInteger::setBit (const int bit)\r
+BigInteger& BigInteger::setBit (const int bit)\r
 {\r
     if (bit >= 0)\r
     {\r
@@ -297,17 +301,21 @@ void BigInteger::setBit (const int bit)
 \r
         getValues() [bitToIndex (bit)] |= bitToMask (bit);\r
     }\r
+\r
+    return *this;\r
 }\r
 \r
-void BigInteger::setBit (const int bit, const bool shouldBeSet)\r
+BigInteger& BigInteger::setBit (const int bit, const bool shouldBeSet)\r
 {\r
     if (shouldBeSet)\r
         setBit (bit);\r
     else\r
         clearBit (bit);\r
+\r
+    return *this;\r
 }\r
 \r
-void BigInteger::clearBit (const int bit) noexcept\r
+BigInteger& BigInteger::clearBit (const int bit) noexcept\r
 {\r
     if (bit >= 0 && bit <= highestBit)\r
     {\r
@@ -316,20 +324,25 @@ void BigInteger::clearBit (const int bit) noexcept
         if (bit == highestBit)\r
             highestBit = getHighestBit();\r
     }\r
+\r
+    return *this;\r
 }\r
 \r
-void BigInteger::setRange (int startBit, int numBits, const bool shouldBeSet)\r
+BigInteger& BigInteger::setRange (int startBit, int numBits, const bool shouldBeSet)\r
 {\r
     while (--numBits >= 0)\r
         setBit (startBit++, shouldBeSet);\r
+\r
+    return *this;\r
 }\r
 \r
-void BigInteger::insertBit (const int bit, const bool shouldBeSet)\r
+BigInteger& BigInteger::insertBit (const int bit, const bool shouldBeSet)\r
 {\r
     if (bit >= 0)\r
         shiftBits (1, bit);\r
 \r
     setBit (bit, shouldBeSet);\r
+    return *this;\r
 }\r
 \r
 //==============================================================================\r
@@ -855,7 +868,7 @@ void BigInteger::shiftRight (int bits, const int startBit)
     }\r
 }\r
 \r
-void BigInteger::shiftBits (int bits, const int startBit)\r
+BigInteger& BigInteger::shiftBits (int bits, const int startBit)\r
 {\r
     if (highestBit >= 0)\r
     {\r
@@ -864,6 +877,8 @@ void BigInteger::shiftBits (int bits, const int startBit)
         else if (bits > 0)\r
             shiftLeft (bits, startBit);\r
     }\r
+\r
+    return *this;\r
 }\r
 \r
 //==============================================================================\r
index 43051381957139c02ce49e86dee7e5114621bf8e..8d35e5f11720941ad52d1ffde6c0fafff9f42070 100644 (file)
@@ -102,16 +102,16 @@ public:
 \r
     //==============================================================================\r
     /** Resets the value to 0. */\r
-    void clear() noexcept;\r
+    BigInteger& clear() noexcept;\r
 \r
     /** Clears a particular bit in the number. */\r
-    void clearBit (int bitNumber) noexcept;\r
+    BigInteger& clearBit (int bitNumber) noexcept;\r
 \r
     /** Sets a specified bit to 1. */\r
-    void setBit (int bitNumber);\r
+    BigInteger& setBit (int bitNumber);\r
 \r
     /** Sets or clears a specified bit. */\r
-    void setBit (int bitNumber, bool shouldBeSet);\r
+    BigInteger& setBit (int bitNumber, bool shouldBeSet);\r
 \r
     /** Sets a range of bits to be either on or off.\r
 \r
@@ -119,10 +119,10 @@ public:
         @param numBits      the number of bits to change\r
         @param shouldBeSet  whether to turn these bits on or off\r
     */\r
-    void setRange (int startBit, int numBits, bool shouldBeSet);\r
+    BigInteger& setRange (int startBit, int numBits, bool shouldBeSet);\r
 \r
     /** Inserts a bit an a given position, shifting up any bits above it. */\r
-    void insertBit (int bitNumber, bool shouldBeSet);\r
+    BigInteger& insertBit (int bitNumber, bool shouldBeSet);\r
 \r
     /** Returns a range of bits as a new BigInteger.\r
 \r
@@ -145,14 +145,14 @@ public:
         Copies the given integer onto a range of bits, starting at startBit,\r
         and using up to numBits of the available bits.\r
     */\r
-    void setBitRangeAsInt (int startBit, int numBits, uint32 valueToSet);\r
+    BigInteger& setBitRangeAsInt (int startBit, int numBits, uint32 valueToSet);\r
 \r
     /** Shifts a section of bits left or right.\r
 \r
         @param howManyBitsLeft  how far to move the bits (+ve numbers shift it left, -ve numbers shift it right).\r
         @param startBit         the first bit to affect - if this is > 0, only bits above that index will be affected.\r
     */\r
-    void shiftBits (int howManyBitsLeft, int startBit);\r
+    BigInteger& shiftBits (int howManyBitsLeft, int startBit);\r
 \r
     /** Returns the total number of set bits in the value. */\r
     int countNumberOfSetBits() const noexcept;\r
index f4dd5e45cf31128c41885d30c98d39c50c4dfe85..49542942d7c576bfedf19ee65870b1d6bf9c9185 100644 (file)
@@ -424,9 +424,8 @@ struct Expression::Helpers
         String getName() const          { return "-"; }\r
         TermPtr negated()               { return input; }\r
 \r
-        TermPtr createTermToEvaluateInput (const Scope& scope, const Term* t, double overallTarget, Term* topLevelTerm) const\r
+        TermPtr createTermToEvaluateInput (const Scope& scope, [[maybe_unused]] const Term* t, double overallTarget, Term* topLevelTerm) const\r
         {\r
-            ignoreUnused (t);\r
             jassert (t == input);\r
 \r
             const Term* const dest = findDestinationFor (topLevelTerm, this);\r
index 166c3a70d824afd2bca2c20dcc457b69a846153b..cc61820ec728fbc415ef1bd2de2e683763863c3f 100644 (file)
@@ -548,7 +548,7 @@ inline int nextPowerOfTwo (int n) noexcept
 int findHighestSetBit (uint32 n) noexcept;\r
 \r
 /** Returns the number of bits in a 32-bit integer. */\r
-inline int countNumberOfBits (uint32 n) noexcept\r
+constexpr int countNumberOfBits (uint32 n) noexcept\r
 {\r
     n -= ((n >> 1) & 0x55555555);\r
     n =  (((n >> 2) & 0x33333333) + (n & 0x33333333));\r
@@ -559,7 +559,7 @@ inline int countNumberOfBits (uint32 n) noexcept
 }\r
 \r
 /** Returns the number of bits in a 64-bit integer. */\r
-inline int countNumberOfBits (uint64 n) noexcept\r
+constexpr int countNumberOfBits (uint64 n) noexcept\r
 {\r
     return countNumberOfBits ((uint32) n) + countNumberOfBits ((uint32) (n >> 32));\r
 }\r
@@ -654,11 +654,8 @@ namespace TypeHelpers
 \r
         @tags{Core}\r
     */\r
-    template <typename Type> struct SmallestFloatType               { using type = float; };\r
-\r
-   #ifndef DOXYGEN\r
-    template <>              struct SmallestFloatType <double>      { using type = double; };\r
-   #endif\r
+    template <typename Type>\r
+    using SmallestFloatType = std::conditional_t<std::is_same_v<Type, double>, double, float>;\r
 \r
     /** These templates are designed to take an integer type, and return an unsigned int\r
         version with the same size.\r
index 9ea8e31925b2868815f5543ba3c8526179a0cc4d..9a71195999b282593431fe4b1332df05db8b2689 100644 (file)
@@ -63,14 +63,14 @@ public:
     }\r
 \r
     /** Returns a range with a given start and length. */\r
-    JUCE_NODISCARD static Range withStartAndLength (const ValueType startValue, const ValueType length) noexcept\r
+    [[nodiscard]] static Range withStartAndLength (const ValueType startValue, const ValueType length) noexcept\r
     {\r
         jassert (length >= ValueType());\r
         return Range (startValue, startValue + length);\r
     }\r
 \r
     /** Returns a range with the specified start position and a length of zero. */\r
-    JUCE_NODISCARD constexpr static Range emptyRange (const ValueType start) noexcept\r
+    [[nodiscard]] constexpr static Range emptyRange (const ValueType start) noexcept\r
     {\r
         return Range (start, start);\r
     }\r
@@ -104,13 +104,13 @@ public:
         If the new start position is higher than the current end of the range, the end point\r
         will be pushed along to equal it, returning an empty range at the new position.\r
     */\r
-    JUCE_NODISCARD constexpr Range withStart (const ValueType newStart) const noexcept\r
+    [[nodiscard]] constexpr Range withStart (const ValueType newStart) const noexcept\r
     {\r
         return Range (newStart, jmax (newStart, end));\r
     }\r
 \r
     /** Returns a range with the same length as this one, but moved to have the given start position. */\r
-    JUCE_NODISCARD constexpr Range movedToStartAt (const ValueType newStart) const noexcept\r
+    [[nodiscard]] constexpr Range movedToStartAt (const ValueType newStart) const noexcept\r
     {\r
         return Range (newStart, end + (newStart - start));\r
     }\r
@@ -130,13 +130,13 @@ public:
         If the new end position is below the current start of the range, the start point\r
         will be pushed back to equal the new end point.\r
     */\r
-    JUCE_NODISCARD constexpr Range withEnd (const ValueType newEnd) const noexcept\r
+    [[nodiscard]] constexpr Range withEnd (const ValueType newEnd) const noexcept\r
     {\r
         return Range (jmin (start, newEnd), newEnd);\r
     }\r
 \r
     /** Returns a range with the same length as this one, but moved to have the given end position. */\r
-    JUCE_NODISCARD constexpr Range movedToEndAt (const ValueType newEnd) const noexcept\r
+    [[nodiscard]] constexpr Range movedToEndAt (const ValueType newEnd) const noexcept\r
     {\r
         return Range (start + (newEnd - end), newEnd);\r
     }\r
@@ -152,7 +152,7 @@ public:
     /** Returns a range with the same start as this one, but a different length.\r
         Lengths less than zero are treated as zero.\r
     */\r
-    JUCE_NODISCARD constexpr Range withLength (const ValueType newLength) const noexcept\r
+    [[nodiscard]] constexpr Range withLength (const ValueType newLength) const noexcept\r
     {\r
         return Range (start, start + newLength);\r
     }\r
@@ -161,7 +161,7 @@ public:
         given amount.\r
         @returns The returned range will be (start - amount, end + amount)\r
     */\r
-    JUCE_NODISCARD constexpr Range expanded (ValueType amount) const noexcept\r
+    [[nodiscard]] constexpr Range expanded (ValueType amount) const noexcept\r
     {\r
         return Range (start - amount, end + amount);\r
     }\r
@@ -231,21 +231,21 @@ public:
 \r
     /** Returns the range that is the intersection of the two ranges, or an empty range\r
         with an undefined start position if they don't overlap. */\r
-    JUCE_NODISCARD constexpr Range getIntersectionWith (Range other) const noexcept\r
+    [[nodiscard]] constexpr Range getIntersectionWith (Range other) const noexcept\r
     {\r
         return Range (jmax (start, other.start),\r
                       jmin (end, other.end));\r
     }\r
 \r
     /** Returns the smallest range that contains both this one and the other one. */\r
-    JUCE_NODISCARD constexpr Range getUnionWith (Range other) const noexcept\r
+    [[nodiscard]] constexpr Range getUnionWith (Range other) const noexcept\r
     {\r
         return Range (jmin (start, other.start),\r
                       jmax (end, other.end));\r
     }\r
 \r
     /** Returns the smallest range that contains both this one and the given value. */\r
-    JUCE_NODISCARD constexpr Range getUnionWith (const ValueType valueToInclude) const noexcept\r
+    [[nodiscard]] constexpr Range getUnionWith (const ValueType valueToInclude) const noexcept\r
     {\r
         return Range (jmin (valueToInclude, start),\r
                       jmax (valueToInclude, end));\r
@@ -270,7 +270,7 @@ public:
     }\r
 \r
     /** Scans an array of values for its min and max, and returns these as a Range. */\r
-    template <typename Integral, std::enable_if_t<std::is_integral<Integral>::value, int> = 0>\r
+    template <typename Integral, std::enable_if_t<std::is_integral_v<Integral>, int> = 0>\r
     static Range findMinAndMax (const ValueType* values, Integral numValues) noexcept\r
     {\r
         if (numValues <= 0)\r
index 1e3fcd2e90a021c38cbb239e092ed9a0bb18fdd7..2eddc07d681ff8a9d1290cf401b9d4f1d523bbd6 100644 (file)
@@ -49,7 +49,7 @@ struct ContainerDeletePolicy
         // implementation of all methods trying to use the OwnedArray (e.g. the destructor\r
         // of the class owning it) into cpp files where they can see to the definition\r
         // of ObjectType. This should fix the error.\r
-        ignoreUnused (sizeof (ObjectType));\r
+        [[maybe_unused]] constexpr auto size = sizeof (ObjectType);\r
 \r
         delete object;\r
     }\r
index 66a669ec05cd1b14010e0996ae63dad19733249c..1d114cc42dc184e87ca34b56cdcf2aa64b3e3ee6 100644 (file)
@@ -87,8 +87,8 @@ class HeapBlock
 {\r
 private:\r
     template <class OtherElementType>\r
-    using AllowConversion = typename std::enable_if<std::is_base_of<typename std::remove_pointer<ElementType>::type,\r
-                                                                    typename std::remove_pointer<OtherElementType>::type>::value>::type;\r
+    using AllowConversion = std::enable_if_t<std::is_base_of_v<std::remove_pointer_t<ElementType>,\r
+                                                               std::remove_pointer_t<OtherElementType>>>;\r
 \r
 public:\r
     //==============================================================================\r
@@ -107,7 +107,7 @@ public:
         If you want an array of zero values, you can use the calloc() method or the\r
         other constructor that takes an InitialisationState parameter.\r
     */\r
-    template <typename SizeType, std::enable_if_t<std::is_convertible<SizeType, int>::value, int> = 0>\r
+    template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>\r
     explicit HeapBlock (SizeType numElements)\r
         : data (static_cast<ElementType*> (std::malloc (static_cast<size_t> (numElements) * sizeof (ElementType))))\r
     {\r
@@ -119,7 +119,7 @@ public:
         The initialiseToZero parameter determines whether the new memory should be cleared,\r
         or left uninitialised.\r
     */\r
-    template <typename SizeType, std::enable_if_t<std::is_convertible<SizeType, int>::value, int> = 0>\r
+    template <typename SizeType, std::enable_if_t<std::is_convertible_v<SizeType, int>, int> = 0>\r
     HeapBlock (SizeType numElements, bool initialiseToZero)\r
         : data (static_cast<ElementType*> (initialiseToZero\r
                                                ? std::calloc (static_cast<size_t> (numElements), sizeof (ElementType))\r
@@ -152,7 +152,7 @@ public:
 \r
     /** Converting move constructor.\r
         Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,\r
-        where std::is_base_of<Base, Derived>::value == true.\r
+        where std::is_base_of_v<Base, Derived> == true.\r
     */\r
     template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>\r
     HeapBlock (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept\r
@@ -163,7 +163,7 @@ public:
 \r
     /** Converting move assignment operator.\r
         Only enabled if this is a HeapBlock<Base*> and the other object is a HeapBlock<Derived*>,\r
-        where std::is_base_of<Base, Derived>::value == true.\r
+        where std::is_base_of_v<Base, Derived> == true.\r
     */\r
     template <class OtherElementType, bool otherThrowOnFailure, typename = AllowConversion<OtherElementType>>\r
     HeapBlock& operator= (HeapBlock<OtherElementType, otherThrowOnFailure>&& other) noexcept\r
index eeac405ae4bc2006f4785a0bd915a4df92a1a12c..3110ad17a026d1ff7785f7a52c262b9459691114 100644 (file)
@@ -84,9 +84,10 @@ inline void writeUnaligned (void* dstPtr, Type value) noexcept
     to a region that has suitable alignment for `Type`, e.g. regions returned from\r
     malloc/calloc that should be suitable for any non-over-aligned type.\r
 */\r
-template <typename Type, typename std::enable_if<std::is_pointer<Type>::value, int>::type = 0>\r
+template <typename Type>\r
 inline Type unalignedPointerCast (void* ptr) noexcept\r
 {\r
+    static_assert (std::is_pointer_v<Type>);\r
     return reinterpret_cast<Type> (ptr);\r
 }\r
 \r
@@ -97,9 +98,10 @@ inline Type unalignedPointerCast (void* ptr) noexcept
     to a region that has suitable alignment for `Type`, e.g. regions returned from\r
     malloc/calloc that should be suitable for any non-over-aligned type.\r
 */\r
-template <typename Type, typename std::enable_if<std::is_pointer<Type>::value, int>::type = 0>\r
+template <typename Type>\r
 inline Type unalignedPointerCast (const void* ptr) noexcept\r
 {\r
+    static_assert (std::is_pointer_v<Type>);\r
     return reinterpret_cast<Type> (ptr);\r
 }\r
 \r
index fbb3cecd6cea8db03cc01aa19b5a00754a4ca2cb..e552df8312e7d7c59dc222fffed00c3b7b1f81bd 100644 (file)
@@ -116,9 +116,6 @@ public:
     */\r
     bool wasObjectDeleted() const noexcept                      { return holder != nullptr && holder->get() == nullptr; }\r
 \r
-    bool operator== (ObjectType* object) const noexcept         { return get() == object; }\r
-    bool operator!= (ObjectType* object) const noexcept         { return get() != object; }\r
-\r
     //==============================================================================\r
     /** This class is used internally by the WeakReference class - don't use it directly\r
         in your code!\r
index 6ed1729a6adbe6883fa58297b90116759f99f9d4..e2a8bbfd1fc31eec3a61a27124e5d1961233ff29 100644 (file)
@@ -30,15 +30,10 @@ namespace detail
     using Void = void;\r
 \r
     template <typename, typename = void>\r
-    struct EqualityComparableToNullptr\r
-        : std::false_type {};\r
+    constexpr auto equalityComparableToNullptr = false;\r
 \r
     template <typename T>\r
-    struct EqualityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>>\r
-        : std::true_type {};\r
-\r
-    template <typename T>\r
-    constexpr bool shouldCheckAgainstNullptr = EqualityComparableToNullptr<T>::value;\r
+    constexpr auto equalityComparableToNullptr<T, Void<decltype (std::declval<T>() != nullptr)>> = true;\r
 } // namespace detail\r
 #endif\r
 \r
@@ -53,23 +48,22 @@ namespace detail
 */\r
 struct NullCheckedInvocation\r
 {\r
-    template <typename Callable, typename... Args,\r
-              std::enable_if_t<detail::shouldCheckAgainstNullptr<Callable>, int> = 0>\r
+    template <typename Callable, typename... Args>\r
     static void invoke (Callable&& fn, Args&&... args)\r
     {\r
-        JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress")\r
+        if constexpr (detail::equalityComparableToNullptr<Callable>)\r
+        {\r
+            JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Waddress")\r
 \r
-        if (fn != nullptr)\r
-            fn (std::forward<Args> (args)...);\r
+            if (fn != nullptr)\r
+                fn (std::forward<Args> (args)...);\r
 \r
-        JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
-    }\r
-\r
-    template <typename Callable, typename... Args,\r
-              std::enable_if_t<! detail::shouldCheckAgainstNullptr<Callable>, int> = 0>\r
-    static void invoke (Callable&& fn, Args&&... args)\r
-    {\r
-        fn (std::forward<Args> (args)...);\r
+            JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+        }\r
+        else\r
+        {\r
+            fn (std::forward<Args> (args)...);\r
+        }\r
     }\r
 \r
     template <typename... Args>\r
@@ -82,14 +76,56 @@ struct NullCheckedInvocation
     Adapted from https://ericniebler.com/2013/08/07/universal-references-and-the-copy-constructo/\r
 */\r
 template <typename A, typename B>\r
-using DisableIfSameOrDerived = typename std::enable_if_t<! std::is_base_of<A, std::remove_reference_t<B>>::value>;\r
+using DisableIfSameOrDerived = std::enable_if_t<! std::is_base_of_v<A, std::remove_reference_t<B>>>;\r
 \r
 /** Copies an object, sets one of the copy's members to the specified value, and then returns the copy. */\r
-template <typename Object, typename OtherObject, typename Member>\r
-Object withMember (Object copy, Member OtherObject::* member, Member&& value)\r
+template <typename Object, typename OtherObject, typename Member, typename Other>\r
+Object withMember (Object copy, Member OtherObject::* member, Other&& value)\r
 {\r
-    copy.*member = std::forward<Member> (value);\r
+    copy.*member = std::forward<Other> (value);\r
     return copy;\r
 }\r
 \r
+/** An easy way to ensure that a function is called at the end of the current\r
+    scope.\r
+\r
+    Usage:\r
+    @code\r
+    {\r
+        if (flag == true)\r
+            return;\r
+\r
+        // While this code executes, flag is true e.g. to prevent reentrancy\r
+        flag = true;\r
+        // When we exit this scope, flag must be false\r
+        const ScopeGuard scope { [&] { flag = false; } };\r
+\r
+        if (checkInitialCondition())\r
+            return; // Scope's lambda will fire here...\r
+\r
+        if (checkCriticalCondition())\r
+            throw std::runtime_error{}; // ...or here...\r
+\r
+        doWorkHavingEstablishedPreconditions();\r
+    } // ...or here!\r
+    @endcode\r
+*/\r
+template <typename Fn> struct ScopeGuard : Fn { ~ScopeGuard() { Fn::operator()(); } };\r
+template <typename Fn> ScopeGuard (Fn) -> ScopeGuard<Fn>;\r
+\r
+#ifndef DOXYGEN\r
+namespace detail\r
+{\r
+template <typename Functor, typename Return, typename... Args>\r
+static constexpr auto toFnPtr (Functor functor, Return (Functor::*) (Args...) const)\r
+{\r
+    return static_cast<Return (*) (Args...)> (functor);\r
+}\r
+} // namespace detail\r
+#endif\r
+\r
+/** Converts a captureless lambda to its equivalent function pointer type. */\r
+template <typename Functor>\r
+static constexpr auto toFnPtr (Functor functor) { return detail::toFnPtr (functor, &Functor::operator()); }\r
+\r
 } // namespace juce\r
index 3f1cd113db1f5c77259c066041f6741928fdf289..ca8d139fb9210a27001cece1f628287021fb842f 100644 (file)
@@ -86,7 +86,22 @@ public:
         writeExternalStorage = 4,\r
 \r
         /** Permission to use camera */\r
-        camera = 5\r
+        camera = 5,\r
+\r
+        /** Permission to read audio files that your app didn't create.\r
+            Has the same effect as readExternalStorage on iOS and Android versions before 33.\r
+        */\r
+        readMediaAudio = 6,\r
+\r
+        /** Permission to read image files that your app didn't create.\r
+            Has the same effect as readExternalStorage on iOS and Android versions before 33.\r
+        */\r
+        readMediaImages = 7,\r
+\r
+        /** Permission to read video files that your app didn't create.\r
+            Has the same effect as readExternalStorage on iOS and Android versions before 33.\r
+        */\r
+        readMediaVideo = 8\r
     };\r
 \r
     //==============================================================================\r
index e0d78f4d8a3d8fa9896477509bca5c4f0ff06daf..f444f9c07fd4d55040c818fe20eb5febd7a81be9 100644 (file)
  #include <iphlpapi.h>\r
  #include <accctrl.h>\r
  #include <aclapi.h>\r
-\r
- #if ! JUCE_CXX17_IS_AVAILABLE\r
-  #pragma push_macro ("WIN_NOEXCEPT")\r
-  #define WIN_NOEXCEPT\r
- #endif\r
-\r
  #include <mapi.h>\r
-\r
- #if ! JUCE_CXX17_IS_AVAILABLE\r
-  #pragma pop_macro ("WIN_NOEXCEPT")\r
- #endif\r
-\r
  #include <float.h>\r
  #include <process.h>\r
  #include <shlobj.h>\r
  #include <sys/ptrace.h>\r
  #include <sys/socket.h>\r
  #include <sys/stat.h>\r
+ #include <sys/syscall.h>\r
  #include <sys/sysinfo.h>\r
  #include <sys/time.h>\r
  #include <sys/types.h>\r
index e3dba249e46e29d6c12a29e98fc57226d7864427..d86eb2f0b95413ee1d4e2aceb1bec7019f4f2b79 100644 (file)
@@ -101,8 +101,7 @@ struct AndroidDocumentDetail
         auto* env = getEnv();\r
         LocalRef<jobjectArray> array { env->NewObjectArray (sizeof... (args), JavaString, nullptr) };\r
 \r
-        int unused[] { (env->SetObjectArrayElement (array.get(), Ix, args.get()), 0)... };\r
-        ignoreUnused (unused);\r
+        (env->SetObjectArrayElement (array.get(), Ix, args.get()), ...);\r
 \r
         return array;\r
     }\r
@@ -745,21 +744,17 @@ struct AndroidDocument::Utils
 };\r
 \r
 //==============================================================================\r
-void AndroidDocumentPermission::takePersistentReadWriteAccess (const URL& url)\r
+void AndroidDocumentPermission::takePersistentReadWriteAccess ([[maybe_unused]] const URL& url)\r
 {\r
    #if JUCE_ANDROID\r
     AndroidDocumentDetail::setPermissions (url, ContentResolver19.takePersistableUriPermission);\r
-   #else\r
-    ignoreUnused (url);\r
    #endif\r
 }\r
 \r
-void AndroidDocumentPermission::releasePersistentReadWriteAccess (const URL& url)\r
+void AndroidDocumentPermission::releasePersistentReadWriteAccess ([[maybe_unused]] const URL& url)\r
 {\r
    #if JUCE_ANDROID\r
     AndroidDocumentDetail::setPermissions (url, ContentResolver19.releasePersistableUriPermission);\r
-   #else\r
-    ignoreUnused (url);\r
    #endif\r
 }\r
 \r
@@ -817,7 +812,7 @@ AndroidDocument AndroidDocument::fromFile (const File& filePath)
                                                 : nullptr };\r
 }\r
 \r
-AndroidDocument AndroidDocument::fromDocument (const URL& documentUrl)\r
+AndroidDocument AndroidDocument::fromDocument ([[maybe_unused]] const URL& documentUrl)\r
 {\r
    #if JUCE_ANDROID\r
     if (getAndroidSDKVersion() < 19)\r
@@ -839,12 +834,11 @@ AndroidDocument AndroidDocument::fromDocument (const URL& documentUrl)
 \r
     return AndroidDocument { Utils::createPimplForSdk (javaUri) };\r
    #else\r
-    ignoreUnused (documentUrl);\r
     return AndroidDocument{};\r
    #endif\r
 }\r
 \r
-AndroidDocument AndroidDocument::fromTree (const URL& treeUrl)\r
+AndroidDocument AndroidDocument::fromTree ([[maybe_unused]] const URL& treeUrl)\r
 {\r
    #if JUCE_ANDROID\r
     if (getAndroidSDKVersion() < 21)\r
@@ -874,7 +868,6 @@ AndroidDocument AndroidDocument::fromTree (const URL& treeUrl)
 \r
     return AndroidDocument { Utils::createPimplForSdk (documentUri) };\r
    #else\r
-    ignoreUnused (treeUrl);\r
     return AndroidDocument{};\r
    #endif\r
 }\r
index 972c6e1dd954a91847a11bfcca1cd086c231a20a..45eb542f433fe42319c796e1b9f9bb007595519a 100644 (file)
@@ -62,7 +62,7 @@ static const uint8 invocationHandleByteCode[] =
  CALLBACK (juce_invokeImplementer, "dispatchInvoke", "(JLjava/lang/Object;Ljava/lang/reflect/Method;[Ljava/lang/Object;)Ljava/lang/Object;") \\r
  CALLBACK (juce_dispatchDelete, "dispatchFinalize", "(J)V")\r
 \r
- DECLARE_JNI_CLASS_WITH_BYTECODE (JuceInvocationHandler, "com/rmsl/juce/JuceInvocationHandler", 10, invocationHandleByteCode, sizeof (invocationHandleByteCode))\r
+ DECLARE_JNI_CLASS_WITH_BYTECODE (JuceInvocationHandler, "com/rmsl/juce/JuceInvocationHandler", 10, invocationHandleByteCode)\r
 #undef JNI_CLASS_MEMBERS\r
 \r
 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
@@ -116,7 +116,7 @@ struct SystemJavaClassComparator
 };\r
 \r
 //==============================================================================\r
-JNIClassBase::JNIClassBase (const char* cp, int classMinSDK, const void* bc, size_t n)\r
+JNIClassBase::JNIClassBase (const char* cp, int classMinSDK, const uint8* bc, size_t n)\r
     : classPath (cp), byteCode (bc), byteCodeSize (n), minSDK (classMinSDK), classRef (nullptr)\r
 {\r
     SystemJavaClassComparator comparator;\r
@@ -552,12 +552,12 @@ static const uint8 javaFragmentOverlay[] =
 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
  METHOD (construct,   "<init>",   "()V") \\r
  METHOD (close,       "close",    "()V") \\r
- CALLBACK (FragmentOverlay::onActivityResultNative, "onActivityResultNative", "(JIILandroid/content/Intent;)V") \\r
- CALLBACK (FragmentOverlay::onCreateNative,         "onCreateNative",         "(JLandroid/os/Bundle;)V") \\r
- CALLBACK (FragmentOverlay::onStartNative,          "onStartNative",          "(J)V") \\r
- CALLBACK (FragmentOverlay::onRequestPermissionsResultNative, "onRequestPermissionsResultNative", "(JI[Ljava/lang/String;[I)V")\r
+ CALLBACK (generatedCallback<&FragmentOverlay::onActivityResultCallback>,           "onActivityResultNative",           "(JIILandroid/content/Intent;)V") \\r
+ CALLBACK (generatedCallback<&FragmentOverlay::onCreatedCallback>,                  "onCreateNative",                   "(JLandroid/os/Bundle;)V") \\r
+ CALLBACK (generatedCallback<&FragmentOverlay::onStartCallback>,                    "onStartNative",                    "(J)V") \\r
+ CALLBACK (generatedCallback<&FragmentOverlay::onRequestPermissionsResultCallback>, "onRequestPermissionsResultNative", "(JI[Ljava/lang/String;[I)V")\r
 \r
- DECLARE_JNI_CLASS_WITH_BYTECODE (JuceFragmentOverlay, "com/rmsl/juce/FragmentOverlay", 16, javaFragmentOverlay, sizeof(javaFragmentOverlay))\r
+ DECLARE_JNI_CLASS_WITH_BYTECODE (JuceFragmentOverlay, "com/rmsl/juce/FragmentOverlay", 16, javaFragmentOverlay)\r
 #undef JNI_CLASS_MEMBERS\r
 \r
 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
@@ -590,47 +590,39 @@ void FragmentOverlay::open()
     env->CallVoidMethod (native.get(), AndroidDialogFragment.show, fm.get(), javaString ("FragmentOverlay").get());\r
 }\r
 \r
-void FragmentOverlay::onActivityResultNative (JNIEnv* env, jobject, jlong host,\r
-                                              jint requestCode, jint resultCode, jobject data)\r
+void FragmentOverlay::onCreatedCallback (JNIEnv* env, FragmentOverlay& t, jobject obj)\r
 {\r
-    if (auto* myself = reinterpret_cast<FragmentOverlay*> (host))\r
-        myself->onActivityResult (requestCode, resultCode, LocalRef<jobject> (env->NewLocalRef (data)));\r
+    t.onCreated (LocalRef<jobject> { env->NewLocalRef (obj) });\r
 }\r
 \r
-void FragmentOverlay::onCreateNative (JNIEnv* env, jobject, jlong host, jobject bundle)\r
+void FragmentOverlay::onStartCallback (JNIEnv*, FragmentOverlay& t)\r
 {\r
-    if (auto* myself = reinterpret_cast<FragmentOverlay*> (host))\r
-        myself->onCreated (LocalRef<jobject> (env->NewLocalRef (bundle)));\r
+    t.onStart();\r
 }\r
 \r
-void FragmentOverlay::onStartNative (JNIEnv*, jobject, jlong host)\r
+void FragmentOverlay::onRequestPermissionsResultCallback (JNIEnv* env, FragmentOverlay& t, jint requestCode, jobjectArray jPermissions, jintArray jGrantResults)\r
 {\r
-    if (auto* myself = reinterpret_cast<FragmentOverlay*> (host))\r
-        myself->onStart();\r
-}\r
+    Array<int> grantResults;\r
+    int n = (jGrantResults != nullptr ? env->GetArrayLength (jGrantResults) : 0);\r
 \r
-void FragmentOverlay::onRequestPermissionsResultNative (JNIEnv* env, jobject, jlong host, jint requestCode,\r
-                                                        jobjectArray jPermissions, jintArray jGrantResults)\r
-{\r
-    if (auto* myself = reinterpret_cast<FragmentOverlay*> (host))\r
+    if (n > 0)\r
     {\r
-        Array<int> grantResults;\r
-        int n = (jGrantResults != nullptr ? env->GetArrayLength (jGrantResults) : 0);\r
+        auto* data = env->GetIntArrayElements (jGrantResults, nullptr);\r
 \r
-        if (n > 0)\r
-        {\r
-            auto* data = env->GetIntArrayElements (jGrantResults, nullptr);\r
+        for (int i = 0; i < n; ++i)\r
+            grantResults.add (data[i]);\r
 \r
-            for (int i = 0; i < n; ++i)\r
-                grantResults.add (data[i]);\r
+        env->ReleaseIntArrayElements (jGrantResults, data, 0);\r
+    }\r
 \r
-            env->ReleaseIntArrayElements (jGrantResults, data, 0);\r
-        }\r
+    t.onRequestPermissionsResult (requestCode,\r
+                                  javaStringArrayToJuce (LocalRef<jobjectArray> (jPermissions)),\r
+                                  grantResults);\r
+}\r
 \r
-        myself->onRequestPermissionsResult (requestCode,\r
-                                            javaStringArrayToJuce (LocalRef<jobjectArray> (jPermissions)),\r
-                                            grantResults);\r
-    }\r
+void FragmentOverlay::onActivityResultCallback (JNIEnv* env, FragmentOverlay& t, jint requestCode, jint resultCode, jobject data)\r
+{\r
+    t.onActivityResult (requestCode, resultCode, LocalRef<jobject> (env->NewLocalRef (data)));\r
 }\r
 \r
 jobject FragmentOverlay::getNativeHandle()\r
@@ -650,8 +642,9 @@ public:
 \r
     void onStart() override\r
     {\r
-        getEnv()->CallVoidMethod (getNativeHandle(), AndroidFragment.startActivityForResult,\r
-                                  intent.get(), requestCode);\r
+        if (! std::exchange (activityHasStarted, true))\r
+            getEnv()->CallVoidMethod (getNativeHandle(), AndroidFragment.startActivityForResult,\r
+                                      intent.get(), requestCode);\r
     }\r
 \r
     void onActivityResult (int activityRequestCode, int resultCode, LocalRef<jobject> data) override\r
@@ -667,6 +660,7 @@ private:
     GlobalRef intent;\r
     int requestCode;\r
     std::function<void (int, int, LocalRef<jobject>)> callback;\r
+    bool activityHasStarted = false;\r
 };\r
 \r
 void startAndroidActivityForResult (const LocalRef<jobject>& intent, int requestCode,\r
index bdfa4c3880495c4618ec29c119b66c3d8a1065df..aeb49f97b2f8a0ce135cc250d90cc18aea9472eb 100644 (file)
@@ -172,7 +172,7 @@ struct SystemJavaClassComparator;
 class JNIClassBase\r
 {\r
 public:\r
-    JNIClassBase (const char* classPath, int minSDK, const void* byteCode, size_t byteCodeSize);\r
+    JNIClassBase (const char* classPath, int minSDK, const uint8* byteCode, size_t byteCodeSize);\r
     virtual ~JNIClassBase();\r
 \r
     operator jclass() const noexcept  { return classRef; }\r
@@ -210,6 +210,9 @@ private:
 };\r
 \r
 //==============================================================================\r
+template <typename T, size_t N> constexpr auto numBytes (const T (&) [N]) { return N; }\r
+                                constexpr auto numBytes (std::nullptr_t)  { return static_cast<size_t> (0); }\r
+\r
 #define CREATE_JNI_METHOD(methodID, stringName, params)          methodID = resolveMethod (env, stringName, params);\r
 #define CREATE_JNI_STATICMETHOD(methodID, stringName, params)    methodID = resolveStaticMethod (env, stringName, params);\r
 #define CREATE_JNI_FIELD(fieldID, stringName, signature)         fieldID  = resolveField (env, stringName, signature);\r
@@ -219,26 +222,26 @@ private:
 #define DECLARE_JNI_FIELD(fieldID, stringName, signature)        jfieldID  fieldID;\r
 #define DECLARE_JNI_CALLBACK(fieldID, stringName, signature)\r
 \r
-#define DECLARE_JNI_CLASS_WITH_BYTECODE(CppClassName, javaPath, minSDK, byteCodeData, byteCodeSize) \\r
-    class CppClassName ## _Class   : public JNIClassBase \\r
-    { \\r
-    public: \\r
-        CppClassName ## _Class() : JNIClassBase (javaPath, minSDK, byteCodeData, byteCodeSize) {} \\r
-    \\r
-        void initialiseFields (JNIEnv* env) \\r
-        { \\r
-            Array<JNINativeMethod> callbacks; \\r
-            JNI_CLASS_MEMBERS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD, CREATE_JNI_CALLBACK); \\r
-            resolveCallbacks (env, callbacks); \\r
-        } \\r
-    \\r
-        JNI_CLASS_MEMBERS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD, DECLARE_JNI_CALLBACK) \\r
-    }; \\r
-    static CppClassName ## _Class CppClassName;\r
+#define DECLARE_JNI_CLASS_WITH_BYTECODE(CppClassName, javaPath, minSDK, byteCodeData)                                                       \\r
+    class CppClassName ## _Class   : public JNIClassBase                                                                                    \\r
+    {                                                                                                                                       \\r
+    public:                                                                                                                                 \\r
+        CppClassName ## _Class() : JNIClassBase (javaPath, minSDK, byteCodeData, numBytes (byteCodeData)) {}                                \\r
+                                                                                                                                            \\r
+        void initialiseFields (JNIEnv* env)                                                                                                 \\r
+        {                                                                                                                                   \\r
+            Array<JNINativeMethod> callbacks;                                                                                               \\r
+            JNI_CLASS_MEMBERS (CREATE_JNI_METHOD, CREATE_JNI_STATICMETHOD, CREATE_JNI_FIELD, CREATE_JNI_STATICFIELD, CREATE_JNI_CALLBACK);  \\r
+            resolveCallbacks (env, callbacks);                                                                                              \\r
+        }                                                                                                                                   \\r
+                                                                                                                                            \\r
+        JNI_CLASS_MEMBERS (DECLARE_JNI_METHOD, DECLARE_JNI_METHOD, DECLARE_JNI_FIELD, DECLARE_JNI_FIELD, DECLARE_JNI_CALLBACK)              \\r
+    };                                                                                                                                      \\r
+    static inline const CppClassName ## _Class CppClassName;\r
 \r
 //==============================================================================\r
 #define DECLARE_JNI_CLASS_WITH_MIN_SDK(CppClassName, javaPath, minSDK) \\r
-    DECLARE_JNI_CLASS_WITH_BYTECODE (CppClassName, javaPath, minSDK, nullptr, 0)\r
+    DECLARE_JNI_CLASS_WITH_BYTECODE (CppClassName, javaPath, minSDK, nullptr)\r
 \r
 //==============================================================================\r
 #define DECLARE_JNI_CLASS(CppClassName, javaPath) \\r
@@ -1005,20 +1008,20 @@ public:
                                              const Array<int>& /*grantResults*/) {}\r
     virtual void onActivityResult (int /*requestCode*/, int /*resultCode*/, LocalRef<jobject> /*data*/) {}\r
 \r
+    /** @internal */\r
+    static void onCreatedCallback (JNIEnv*, FragmentOverlay&, jobject obj);\r
+    /** @internal */\r
+    static void onStartCallback (JNIEnv*, FragmentOverlay&);\r
+    /** @internal */\r
+    static void onRequestPermissionsResultCallback (JNIEnv*, FragmentOverlay&, jint requestCode, jobjectArray jPermissions, jintArray jGrantResults);\r
+    /** @internal */\r
+    static void onActivityResultCallback (JNIEnv*, FragmentOverlay&, jint requestCode, jint resultCode, jobject data);\r
+\r
 protected:\r
     jobject getNativeHandle();\r
 \r
 private:\r
-\r
     GlobalRef native;\r
-\r
-public:\r
-    /* internal: do not use */\r
-    static void onActivityResultNative (JNIEnv*, jobject, jlong, jint, jint, jobject);\r
-    static void onCreateNative (JNIEnv*, jobject, jlong, jobject);\r
-    static void onStartNative (JNIEnv*, jobject, jlong);\r
-    static void onRequestPermissionsResultNative (JNIEnv*, jobject, jlong, jint,\r
-                                                  jobjectArray, jintArray);\r
 };\r
 \r
 //==============================================================================\r
@@ -1030,4 +1033,30 @@ void startAndroidActivityForResult (const LocalRef<jobject>& intent, int request
 bool androidHasSystemFeature (const String& property);\r
 String audioManagerGetProperty (const String& property);\r
 \r
+namespace detail\r
+{\r
+\r
+template <auto Fn, typename Result, typename Class, typename... Args>\r
+inline constexpr auto generatedCallbackImpl =\r
+    juce::toFnPtr (JNICALL [] (JNIEnv* env, jobject, jlong host, Args... args) -> Result\r
+                   {\r
+                       if (auto* object = reinterpret_cast<Class*> (host))\r
+                           return Fn (env, *object, args...);\r
+\r
+                       return {};\r
+                   });\r
+\r
+template <auto Fn, typename Result, typename Class, typename... Args>\r
+constexpr auto generateCallbackImpl (Result (*) (JNIEnv*, Class&, Args...))        { return generatedCallbackImpl<Fn, Result, Class, Args...>; }\r
+\r
+template <auto Fn, typename Result, typename Class, typename... Args>\r
+constexpr auto generateCallbackImpl (Result (*) (JNIEnv*, const Class&, Args...))  { return generatedCallbackImpl<Fn, Result, Class, Args...>; }\r
+\r
+} // namespace detail\r
+\r
+// Evaluates to a static function that forwards to the provided Fn, assuming that the\r
+// 'host' argument points to an object on which it is valid to call Fn\r
+template <auto Fn>\r
+inline constexpr auto generatedCallback = detail::generateCallbackImpl<Fn> (Fn);\r
+\r
 } // namespace juce\r
index f5a3afa89b6e05b4b5e4dc5909e945b49d9e423c..c128cc6926ff2ca7e65ce5370a409ea6f629bdab 100644 (file)
@@ -195,7 +195,7 @@ DECLARE_JNI_CLASS (StringBuffer, "java/lang/StringBuffer")
  METHOD (isExhausted, "isExhausted", "()Z") \\r
  METHOD (setPosition, "setPosition", "(J)Z") \\r
 \r
-DECLARE_JNI_CLASS_WITH_BYTECODE (HTTPStream, "com/rmsl/juce/JuceHTTPStream", 16, javaJuceHttpStream, sizeof(javaJuceHttpStream))\r
+DECLARE_JNI_CLASS_WITH_BYTECODE (HTTPStream, "com/rmsl/juce/JuceHTTPStream", 16, javaJuceHttpStream)\r
 #undef JNI_CLASS_MEMBERS\r
 \r
 //==============================================================================\r
index 1bbc073b7518e226cd9d0d5a6c6690596be9e1b8..285b92c1e16687f01b636d4c59d330855edc8b29 100644 (file)
@@ -24,15 +24,47 @@ namespace juce
 {\r
 \r
 //==============================================================================\r
-static String jucePermissionToAndroidPermission (RuntimePermissions::PermissionID permission)\r
+static StringArray jucePermissionToAndroidPermissions (RuntimePermissions::PermissionID permission)\r
 {\r
+    const auto externalStorageOrMedia = [] (const auto* newPermission)\r
+    {\r
+        return getAndroidSDKVersion() < 33 ? "android.permission.READ_EXTERNAL_STORAGE" : newPermission;\r
+    };\r
+\r
     switch (permission)\r
     {\r
-        case RuntimePermissions::recordAudio:           return "android.permission.RECORD_AUDIO";\r
-        case RuntimePermissions::bluetoothMidi:         return "android.permission.ACCESS_FINE_LOCATION";\r
-        case RuntimePermissions::readExternalStorage:   return "android.permission.READ_EXTERNAL_STORAGE";\r
-        case RuntimePermissions::writeExternalStorage:  return "android.permission.WRITE_EXTERNAL_STORAGE";\r
-        case RuntimePermissions::camera:                return "android.permission.CAMERA";\r
+        case RuntimePermissions::recordAudio:           return { "android.permission.RECORD_AUDIO" };\r
+        case RuntimePermissions::bluetoothMidi:\r
+        {\r
+            if (getAndroidSDKVersion() < 31)\r
+                return { "android.permission.ACCESS_FINE_LOCATION" };\r
+\r
+            return { "android.permission.BLUETOOTH_SCAN",\r
+                     "android.permission.BLUETOOTH_CONNECT" };\r
+        }\r
+\r
+        case RuntimePermissions::writeExternalStorage:  return { "android.permission.WRITE_EXTERNAL_STORAGE" };\r
+        case RuntimePermissions::camera:                return { "android.permission.CAMERA" };\r
+\r
+        case RuntimePermissions::readExternalStorage:\r
+        {\r
+            // See: https://developer.android.com/reference/android/Manifest.permission#READ_EXTERNAL_STORAGE\r
+            if (getAndroidSDKVersion() < 33)\r
+                return { "android.permission.READ_EXTERNAL_STORAGE" };\r
+\r
+            return { "android.permission.READ_MEDIA_AUDIO",\r
+                     "android.permission.READ_MEDIA_IMAGES",\r
+                     "android.permission.READ_MEDIA_VIDEO" };\r
+        }\r
+\r
+        case RuntimePermissions::readMediaAudio:\r
+            return { externalStorageOrMedia ("android.permission.READ_MEDIA_AUDIO") };\r
+\r
+        case RuntimePermissions::readMediaImages:\r
+            return { externalStorageOrMedia ("android.permission.READ_MEDIA_IMAGES") };\r
+\r
+        case RuntimePermissions::readMediaVideo:\r
+            return { externalStorageOrMedia ("android.permission.READ_MEDIA_VIDEO") };\r
     }\r
 \r
     // invalid permission\r
@@ -42,53 +74,29 @@ static String jucePermissionToAndroidPermission (RuntimePermissions::PermissionI
 \r
 static RuntimePermissions::PermissionID androidPermissionToJucePermission (const String& permission)\r
 {\r
-    if      (permission == "android.permission.RECORD_AUDIO")            return RuntimePermissions::recordAudio;\r
-    else if (permission == "android.permission.ACCESS_FINE_LOCATION")    return RuntimePermissions::bluetoothMidi;\r
-    else if (permission == "android.permission.READ_EXTERNAL_STORAGE")   return RuntimePermissions::readExternalStorage;\r
-    else if (permission == "android.permission.WRITE_EXTERNAL_STORAGE")  return RuntimePermissions::writeExternalStorage;\r
-    else if (permission == "android.permission.CAMERA")                  return RuntimePermissions::camera;\r
+    static const std::map<String, RuntimePermissions::PermissionID> map\r
+    {\r
+        { "android.permission.RECORD_AUDIO",            RuntimePermissions::recordAudio },\r
+        { "android.permission.ACCESS_FINE_LOCATION",    RuntimePermissions::bluetoothMidi },\r
+        { "android.permission.READ_EXTERNAL_STORAGE",   RuntimePermissions::readExternalStorage },\r
+        { "android.permission.WRITE_EXTERNAL_STORAGE",  RuntimePermissions::writeExternalStorage },\r
+        { "android.permission.CAMERA",                  RuntimePermissions::camera },\r
+        { "android.permission.READ_MEDIA_AUDIO",        RuntimePermissions::readMediaAudio },\r
+        { "android.permission.READ_MEDIA_IMAGES",       RuntimePermissions::readMediaImages },\r
+        { "android.permission.READ_MEDIA_VIDEO",        RuntimePermissions::readMediaVideo },\r
+        { "android.permission.BLUETOOTH_SCAN",          RuntimePermissions::bluetoothMidi },\r
+    };\r
 \r
-    return static_cast<RuntimePermissions::PermissionID> (-1);\r
+    const auto iter = map.find (permission);\r
+    return iter != map.cend() ? iter->second\r
+                              : static_cast<RuntimePermissions::PermissionID> (-1);\r
 }\r
 \r
 //==============================================================================\r
 struct PermissionsRequest\r
 {\r
-    PermissionsRequest() {}\r
-\r
-    // using "= default" on the following method triggers an internal compiler error\r
-    // in Android NDK 17\r
-    PermissionsRequest (const PermissionsRequest& o)\r
-        : callback (o.callback), permission (o.permission)\r
-    {}\r
-\r
-    PermissionsRequest (PermissionsRequest&& o)\r
-        : callback (std::move (o.callback)), permission (o.permission)\r
-    {\r
-        o.permission = static_cast<RuntimePermissions::PermissionID> (-1);\r
-    }\r
-\r
-    PermissionsRequest (RuntimePermissions::Callback && callbackToUse,\r
-                        RuntimePermissions::PermissionID permissionToRequest)\r
-        : callback (std::move (callbackToUse)), permission (permissionToRequest)\r
-    {}\r
-\r
-    PermissionsRequest& operator= (const PermissionsRequest & o)\r
-    {\r
-        callback   = o.callback;\r
-        permission = o.permission;\r
-        return *this;\r
-    }\r
-\r
-    PermissionsRequest& operator= (PermissionsRequest && o)\r
-    {\r
-        callback   = std::move (o.callback);\r
-        permission = o.permission;\r
-        return *this;\r
-    }\r
-\r
     RuntimePermissions::Callback callback;\r
-    RuntimePermissions::PermissionID permission;\r
+    RuntimePermissions::PermissionID permission = static_cast<RuntimePermissions::PermissionID> (-1);\r
 };\r
 \r
 //==============================================================================\r
@@ -165,8 +173,7 @@ struct PermissionsOverlay   : FragmentOverlay
             {\r
                 auto &request = requests.front();\r
 \r
-                StringArray permissionsArray{\r
-                        jucePermissionToAndroidPermission (request.permission)};\r
+                auto permissionsArray = jucePermissionToAndroidPermissions (request.permission);\r
                 auto jPermissionsArray = juceStringArrayToJava (permissionsArray);\r
 \r
 \r
@@ -199,9 +206,16 @@ struct PermissionsOverlay   : FragmentOverlay
 //==============================================================================\r
 void RuntimePermissions::request (PermissionID permission, Callback callback)\r
 {\r
-    auto requestedPermission = jucePermissionToAndroidPermission (permission);\r
+    const auto requestedPermissions = jucePermissionToAndroidPermissions (permission);\r
+\r
+    const auto allPermissionsInManifest = std::all_of (requestedPermissions.begin(),\r
+                                                       requestedPermissions.end(),\r
+                                                       [] (const auto& p)\r
+                                                       {\r
+                                                           return isPermissionDeclaredInManifest (p);\r
+                                                       });\r
 \r
-    if (! isPermissionDeclaredInManifest (requestedPermission))\r
+    if (! allPermissionsInManifest)\r
     {\r
         // Error! If you want to be able to request this runtime permission, you\r
         // also need to declare it in your app's manifest. You can do so via\r
@@ -220,7 +234,7 @@ void RuntimePermissions::request (PermissionID permission, Callback callback)
         return;\r
     }\r
 \r
-    PermissionsRequest request (std::move (callback), permission);\r
+    PermissionsRequest request { std::move (callback), permission };\r
 \r
     static CriticalSection overlayGuard;\r
     ScopedLock lock (overlayGuard);\r
@@ -250,12 +264,15 @@ bool RuntimePermissions::isGranted (PermissionID permission)
 {\r
     auto* env = getEnv();\r
 \r
-    auto requestedPermission = jucePermissionToAndroidPermission (permission);\r
-    int result = env->CallIntMethod (getAppContext().get(), AndroidContext.checkCallingOrSelfPermission,\r
-                                     javaString (requestedPermission).get());\r
+    const auto requestedPermissions = jucePermissionToAndroidPermissions (permission);\r
 \r
+    return std::all_of (requestedPermissions.begin(), requestedPermissions.end(), [env] (const auto& p)\r
+    {\r
+        return 0 == env->CallIntMethod (getAppContext().get(),\r
+                                        AndroidContext.checkCallingOrSelfPermission,\r
+                                        javaString (p).get());\r
+    });\r
 \r
-    return result == 0 /* PERMISSION_GRANTED */;\r
 }\r
 \r
 } // namespace juce\r
index 8c3e416df8b4323fa59e295e5b474ff9465eda53..4000613c693ca936b5400a29fe7ff3dfac7827cb 100644 (file)
@@ -47,6 +47,22 @@ namespace AndroidStatsHelpers
                                                                                           javaString (name).get())));\r
     }\r
 \r
+    static String getAndroidID()\r
+    {\r
+        auto* env = getEnv();\r
+\r
+        if (auto settings = (jclass) env->FindClass ("android/provider/Settings$Secure"))\r
+        {\r
+            if (auto fId = env->GetStaticFieldID (settings, "ANDROID_ID", "Ljava/lang/String;"))\r
+            {\r
+                auto androidID = (jstring) env->GetStaticObjectField (settings, fId);\r
+                return juceString (LocalRef<jstring> (androidID));\r
+            }\r
+        }\r
+\r
+        return "";\r
+    }\r
+\r
     static String getLocaleValue (bool isRegion)\r
     {\r
         auto* env = getEnv();\r
@@ -170,6 +186,15 @@ String SystemStats::getUserLanguage()    { return AndroidStatsHelpers::getLocale
 String SystemStats::getUserRegion()      { return AndroidStatsHelpers::getLocaleValue (true); }\r
 String SystemStats::getDisplayLanguage() { return getUserLanguage() + "-" + getUserRegion(); }\r
 \r
+String SystemStats::getUniqueDeviceID()\r
+{\r
+    auto id = String ((uint64_t) AndroidStatsHelpers::getAndroidID().hashCode64());\r
+\r
+    // Please tell someone at JUCE if this occurs\r
+    jassert (id.isNotEmpty());\r
+    return id;\r
+}\r
+\r
 //==============================================================================\r
 void CPUInformation::initialise() noexcept\r
 {\r
index 796328aa0ca2b3d5a0fcf2f446bec87abc56131b..fe6088553a98b0363daa2b54cc32782cb36d353e 100644 (file)
@@ -344,36 +344,95 @@ LocalRef<jobject> getMainActivity() noexcept
 }\r
 \r
 //==============================================================================\r
-// sets the process to 0=low priority, 1=normal, 2=high, 3=realtime\r
-JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority prior)\r
+using RealtimeThreadFactory = pthread_t (*) (void* (*entry) (void*), void* userPtr);\r
+// This is defined in the juce_audio_devices module, with different definitions depending on\r
+// whether OpenSL/Oboe are enabled.\r
+RealtimeThreadFactory getAndroidRealtimeThreadFactory();\r
+\r
+#if ! JUCE_MODULE_AVAILABLE_juce_audio_devices\r
+RealtimeThreadFactory getAndroidRealtimeThreadFactory() { return nullptr; }\r
+#endif\r
+\r
+extern JavaVM* androidJNIJavaVM;\r
+\r
+static auto setPriorityOfThisThread (Thread::Priority p)\r
 {\r
-    // TODO\r
+    return setpriority (PRIO_PROCESS,\r
+                        (id_t) gettid(),\r
+                        ThreadPriorities::getNativePriority (p)) == 0;\r
+}\r
 \r
-    struct sched_param param;\r
-    int policy, maxp, minp;\r
+bool Thread::createNativeThread (Priority)\r
+{\r
+    const auto threadEntryProc = [] (void* userData) -> void*\r
+    {\r
+        auto* myself = static_cast<Thread*> (userData);\r
 \r
-    const int p = (int) prior;\r
+        setPriorityOfThisThread (myself->priority);\r
 \r
-    if (p <= 1)\r
-        policy = SCHED_OTHER;\r
-    else\r
-        policy = SCHED_RR;\r
+        juce_threadEntryPoint (myself);\r
 \r
-    minp = sched_get_priority_min (policy);\r
-    maxp = sched_get_priority_max (policy);\r
+        if (androidJNIJavaVM != nullptr)\r
+        {\r
+            void* env = nullptr;\r
+            androidJNIJavaVM->GetEnv (&env, JNI_VERSION_1_2);\r
 \r
-    if (p < 2)\r
-        param.sched_priority = 0;\r
-    else if (p == 2 )\r
-        // Set to middle of lower realtime priority range\r
-        param.sched_priority = minp + (maxp - minp) / 4;\r
-    else\r
-        // Set to middle of higher realtime priority range\r
-        param.sched_priority = minp + (3 * (maxp - minp) / 4);\r
+            // only detach if we have actually been attached\r
+            if (env != nullptr)\r
+                androidJNIJavaVM->DetachCurrentThread();\r
+        }\r
+\r
+        return nullptr;\r
+    };\r
+\r
+    if (isRealtime())\r
+    {\r
+        if (const auto factory = getAndroidRealtimeThreadFactory())\r
+        {\r
+            threadHandle = (void*) factory (threadEntryProc, this);\r
+            threadId = (ThreadID) threadHandle.load();\r
+            return threadId != nullptr;\r
+        }\r
+        else\r
+        {\r
+            jassertfalse;\r
+        }\r
+    }\r
+\r
+    PosixThreadAttribute attr { threadStackSize };\r
+    threadId = threadHandle = makeThreadHandle (attr, this, threadEntryProc);\r
 \r
-    pthread_setschedparam (pthread_self(), policy, &param);\r
+    return threadId != nullptr;\r
 }\r
 \r
+void Thread::killThread()\r
+{\r
+    if (threadHandle != nullptr)\r
+        jassertfalse; // pthread_cancel not available!\r
+}\r
+\r
+Thread::Priority Thread::getPriority() const\r
+{\r
+    jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+    const auto native = getpriority (PRIO_PROCESS, (id_t) gettid());\r
+    return ThreadPriorities::getJucePriority (native);\r
+}\r
+\r
+bool Thread::setPriority (Priority priorityIn)\r
+{\r
+    jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+    if (isRealtime())\r
+        return false;\r
+\r
+    const auto priorityToUse = priority = priorityIn;\r
+    return setPriorityOfThisThread (priorityToUse) == 0;\r
+}\r
+\r
+//==============================================================================\r
+JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority) {}\r
+\r
 JUCE_API bool JUCE_CALLTYPE juce_isRunningUnderDebugger() noexcept\r
 {\r
     StringArray lines;\r
index 84abf88eab415dbbaa1d6a30a0bc62f323b04373..5366995f121c3089e8c1b72f9d3b91ed0aa4d5a6 100644 (file)
@@ -304,6 +304,64 @@ void CPUInformation::initialise() noexcept
   #endif\r
 }\r
 \r
+String SystemStats::getUniqueDeviceID()\r
+{\r
+    static const auto deviceId = []()\r
+    {\r
+        const auto call = [] (auto command) -> String\r
+        {\r
+            ChildProcess proc;\r
+\r
+            if (proc.start (command, ChildProcess::wantStdOut))\r
+                return proc.readAllProcessOutput();\r
+\r
+            return {};\r
+        };\r
+\r
+        auto data = call ("cat /sys/class/dmi/id/board_serial");\r
+\r
+        // 'board_serial' is enough on its own, fallback to bios stuff if we can't find it.\r
+        if (data.isEmpty())\r
+        {\r
+            data = call ("cat /sys/class/dmi/id/bios_date")\r
+                 + call ("cat /sys/class/dmi/id/bios_release")\r
+                 + call ("cat /sys/class/dmi/id/bios_vendor")\r
+                 + call ("cat /sys/class/dmi/id/bios_version");\r
+        }\r
+\r
+        auto cpuData = call ("lscpu");\r
+\r
+        if (cpuData.isNotEmpty())\r
+        {\r
+            auto getCpuInfo = [&cpuData] (auto key) -> String\r
+            {\r
+                auto index = cpuData.indexOf (key);\r
+\r
+                if (index >= 0)\r
+                {\r
+                    auto start = cpuData.indexOf (index, ":");\r
+                    auto end = cpuData.indexOf (start, "\n");\r
+\r
+                    return cpuData.substring (start + 1, end).trim();\r
+                }\r
+\r
+                return {};\r
+            };\r
+\r
+            data += getCpuInfo ("CPU family:");\r
+            data += getCpuInfo ("Model:");\r
+            data += getCpuInfo ("Model name:");\r
+            data += getCpuInfo ("Vendor ID:");\r
+        }\r
+\r
+        return String ((uint64_t) data.hashCode64());\r
+    }();\r
+\r
+    // Please tell someone at JUCE if this occurs\r
+    jassert (deviceId.isNotEmpty());\r
+    return deviceId;\r
+}\r
+\r
 //==============================================================================\r
 uint32 juce_millisecondsSinceStartup() noexcept\r
 {\r
index 9f9c07b7b122f496fe1b20f5afa88aa16a4a3562..6abf6586756b4ce54babae10ef9cfded8f23b5ae 100644 (file)
@@ -28,27 +28,49 @@ namespace juce
     live in juce_posix_SharedCode.h!\r
 */\r
 \r
-//==============================================================================\r
-JUCE_API void JUCE_CALLTYPE Process::setPriority (const ProcessPriority prior)\r
+bool Thread::createNativeThread (Priority)\r
 {\r
-    auto policy = (prior <= NormalPriority) ? SCHED_OTHER : SCHED_RR;\r
-    auto minp = sched_get_priority_min (policy);\r
-    auto maxp = sched_get_priority_max (policy);\r
-\r
-    struct sched_param param;\r
+    PosixThreadAttribute attr { threadStackSize };\r
+    PosixSchedulerPriority::getNativeSchedulerAndPriority (realtimeOptions, {}).apply (attr);\r
 \r
-    switch (prior)\r
+    threadId = threadHandle = makeThreadHandle (attr, this, [] (void* userData) -> void*\r
     {\r
-        case LowPriority:\r
-        case NormalPriority:    param.sched_priority = 0; break;\r
-        case HighPriority:      param.sched_priority = minp + (maxp - minp) / 4; break;\r
-        case RealtimePriority:  param.sched_priority = minp + (3 * (maxp - minp) / 4); break;\r
-        default:                jassertfalse; break;\r
-    }\r
-\r
-    pthread_setschedparam (pthread_self(), policy, &param);\r
+        auto* myself = static_cast<Thread*> (userData);\r
+\r
+        juce_threadEntryPoint (myself);\r
+\r
+        return nullptr;\r
+    });\r
+\r
+    return threadId != nullptr;\r
+}\r
+\r
+void Thread::killThread()\r
+{\r
+    if (threadHandle != nullptr)\r
+        pthread_cancel ((pthread_t) threadHandle.load());\r
+}\r
+\r
+// Until we implement Nice awareness, these don't do anything on Linux.\r
+Thread::Priority Thread::getPriority() const\r
+{\r
+    jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+    return priority;\r
 }\r
 \r
+bool Thread::setPriority (Priority newPriority)\r
+{\r
+    jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+    // Return true to make it compatible with other platforms.\r
+    priority = newPriority;\r
+    return true;\r
+}\r
+\r
+//==============================================================================\r
+JUCE_API void JUCE_CALLTYPE Process::setPriority (ProcessPriority) {}\r
+\r
 static bool swapUserAndEffectiveUser()\r
 {\r
     auto result1 = setreuid (geteuid(), getuid());\r
index edeca6df5f2565088b24509af85647e3cfdb5648..57a17db18dface9e1fa3c80dd4f06125e77b5a35 100644 (file)
@@ -37,7 +37,7 @@ struct CFObjectDeleter
 };\r
 \r
 template <typename CFType>\r
-using CFUniquePtr = std::unique_ptr<typename std::remove_pointer<CFType>::type, CFObjectDeleter<CFType>>;\r
+using CFUniquePtr = std::unique_ptr<std::remove_pointer_t<CFType>, CFObjectDeleter<CFType>>;\r
 \r
 template <typename CFType>\r
 struct CFObjectHolder\r
index dcee53f11a56ab54301928f5cbcf21f1e7707dea..ffd68758aee1c006f6db6cc8c30b9e370fa6c968 100644 (file)
@@ -397,7 +397,7 @@ bool DirectoryIterator::NativeIterator::next (String& filenameFound,
 \r
 \r
 //==============================================================================\r
-bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String& parameters)\r
+bool JUCE_CALLTYPE Process::openDocument (const String& fileName, [[maybe_unused]] const String& parameters)\r
 {\r
     JUCE_AUTORELEASEPOOL\r
     {\r
@@ -406,8 +406,6 @@ bool JUCE_CALLTYPE Process::openDocument (const String& fileName, const String&
                                                                                        : [NSURL URLWithString: fileNameAsNS];\r
 \r
       #if JUCE_IOS\r
-        ignoreUnused (parameters);\r
-\r
         if (@available (iOS 10.0, *))\r
         {\r
             [[UIApplication sharedApplication] openURL: filenameAsURL\r
index 51939b48488741510515ab42e96048efc2e2835b..56110874d2c5a6f44120ecc342e9ac13508bad01 100644 (file)
@@ -58,14 +58,12 @@ void MACAddress::findAllAddresses (Array<MACAddress>& result)
 }\r
 \r
 //==============================================================================\r
-bool JUCE_CALLTYPE Process::openEmailWithAttachments (const String& targetEmailAddress,\r
-                                                      const String& emailSubject,\r
-                                                      const String& bodyText,\r
-                                                      const StringArray& filesToAttach)\r
+bool JUCE_CALLTYPE Process::openEmailWithAttachments ([[maybe_unused]] const String& targetEmailAddress,\r
+                                                      [[maybe_unused]] const String& emailSubject,\r
+                                                      [[maybe_unused]] const String& bodyText,\r
+                                                      [[maybe_unused]] const StringArray& filesToAttach)\r
 {\r
   #if JUCE_IOS\r
-    ignoreUnused (targetEmailAddress, emailSubject, bodyText, filesToAttach);\r
-\r
     //xxx probably need to use MFMailComposeViewController\r
     jassertfalse;\r
     return false;\r
@@ -282,9 +280,9 @@ public:
         return newRequest;\r
     }\r
 \r
-    void didFailWithError (NSError* error)\r
+    void didFailWithError ([[maybe_unused]] NSError* error)\r
     {\r
-        DBG (nsStringToJuce ([error description])); ignoreUnused (error);\r
+        DBG (nsStringToJuce ([error description]));\r
         nsUrlErrorCode = [error code];\r
         hasFailed = true;\r
         initialised = true;\r
@@ -951,10 +949,8 @@ public:
         connection.reset();\r
     }\r
 \r
-    bool connect (WebInputStream::Listener* webInputListener, int numRetries = 0)\r
+    bool connect (WebInputStream::Listener* webInputListener, [[maybe_unused]] int numRetries = 0)\r
     {\r
-        ignoreUnused (numRetries);\r
-\r
         {\r
             const ScopedLock lock (createConnectionLock);\r
 \r
index 8995472d650615cc23197e7a690805dd9687826f..7f17c07b95900e4102a2b5367f1a393fa14f2d91 100644 (file)
@@ -342,15 +342,6 @@ namespace detail
     {\r
         return joinCompileTimeStr (v, makeCompileTimeStr (others...));\r
     }\r
-\r
-    template <typename Functor, typename Return, typename... Args>\r
-    static constexpr auto toFnPtr (Functor functor, Return (Functor::*) (Args...) const)\r
-    {\r
-        return static_cast<Return (*) (Args...)> (functor);\r
-    }\r
-\r
-    template <typename Functor>\r
-    static constexpr auto toFnPtr (Functor functor) { return toFnPtr (functor, &Functor::operator()); }\r
 } // namespace detail\r
 \r
 //==============================================================================\r
@@ -391,12 +382,12 @@ struct ObjCClass
     template <typename Type>\r
     void addIvar (const char* name)\r
     {\r
-        BOOL b = class_addIvar (cls, name, sizeof (Type), (uint8_t) rint (log2 (sizeof (Type))), @encode (Type));\r
-        jassert (b); ignoreUnused (b);\r
+        [[maybe_unused]] BOOL b = class_addIvar (cls, name, sizeof (Type), (uint8_t) rint (log2 (sizeof (Type))), @encode (Type));\r
+        jassert (b);\r
     }\r
 \r
     template <typename Fn>\r
-    void addMethod (SEL selector, Fn callbackFn) { addMethod (selector, detail::toFnPtr (callbackFn)); }\r
+    void addMethod (SEL selector, Fn callbackFn) { addMethod (selector, toFnPtr (callbackFn)); }\r
 \r
     template <typename Result, typename... Args>\r
     void addMethod (SEL selector, Result (*callbackFn) (id, SEL, Args...))\r
@@ -408,8 +399,8 @@ struct ObjCClass
 \r
     void addProtocol (Protocol* protocol)\r
     {\r
-        BOOL b = class_addProtocol (cls, protocol);\r
-        jassert (b); ignoreUnused (b);\r
+        [[maybe_unused]] BOOL b = class_addProtocol (cls, protocol);\r
+        jassert (b);\r
     }\r
 \r
     template <typename ReturnType, typename... Params>\r
@@ -492,13 +483,31 @@ Class* getJuceClassFromNSObject (NSObject* obj)
     return obj != nullptr ? getIvar<Class*> (obj, "cppObject") : nullptr;\r
 }\r
 \r
-template <typename ReturnT, class Class, typename... Params>\r
-ReturnT (^CreateObjCBlock(Class* object, ReturnT (Class::*fn)(Params...))) (Params...)\r
+namespace detail\r
 {\r
-    __block Class* _this = object;\r
-    __block ReturnT (Class::*_fn)(Params...) = fn;\r
+template <typename> struct Signature;\r
+template <typename R, typename... A> struct Signature<R (A...)> {};\r
+\r
+template <typename Class, typename Result, typename... Args>\r
+constexpr auto getSignature (Result (Class::*) (Args...))       { return Signature<Result (Args...)>{}; }\r
+\r
+template <typename Class, typename Result, typename... Args>\r
+constexpr auto getSignature (Result (Class::*) (Args...) const) { return Signature<Result (Args...)>{}; }\r
 \r
-    return [[^ReturnT (Params... params) { return (_this->*_fn) (params...); } copy] autorelease];\r
+template <typename Class, typename Fn, typename Result, typename... Params>\r
+auto createObjCBlockImpl (Class* object, Fn func, Signature<Result (Params...)>)\r
+{\r
+    __block auto _this = object;\r
+    __block auto _func = func;\r
+\r
+    return [[^Result (Params... params) { return (_this->*_func) (params...); } copy] autorelease];\r
+}\r
+} // namespace detail\r
+\r
+template <typename Class, typename MemberFunc>\r
+auto CreateObjCBlock (Class* object, MemberFunc fn)\r
+{\r
+    return detail::createObjCBlockImpl (object, fn, detail::getSignature (fn));\r
 }\r
 \r
 template <typename BlockType>\r
@@ -526,22 +535,26 @@ class ScopedNotificationCenterObserver
 public:\r
     ScopedNotificationCenterObserver() = default;\r
 \r
-    ScopedNotificationCenterObserver (id observerIn, SEL selector, NSNotificationName nameIn, id objectIn)\r
-        : observer (observerIn), name (nameIn), object (objectIn)\r
+    ScopedNotificationCenterObserver (id observerIn,\r
+                                      SEL selector,\r
+                                      NSNotificationName nameIn,\r
+                                      id objectIn,\r
+                                      Class klassIn = [NSNotificationCenter class])\r
+        : observer (observerIn), name (nameIn), object (objectIn), klass (klassIn)\r
     {\r
-        [[NSNotificationCenter defaultCenter] addObserver: observer\r
-                                                 selector: selector\r
-                                                     name: name\r
-                                                   object: object];\r
+        [[klass defaultCenter] addObserver: observer\r
+                                  selector: selector\r
+                                      name: name\r
+                                    object: object];\r
     }\r
 \r
     ~ScopedNotificationCenterObserver()\r
     {\r
         if (observer != nullptr && name != nullptr)\r
         {\r
-            [[NSNotificationCenter defaultCenter] removeObserver: observer\r
-                                                            name: name\r
-                                                          object: object];\r
+            [[klass defaultCenter] removeObserver: observer\r
+                                             name: name\r
+                                           object: object];\r
         }\r
     }\r
 \r
@@ -552,8 +565,7 @@ public:
 \r
     ScopedNotificationCenterObserver& operator= (ScopedNotificationCenterObserver&& other) noexcept\r
     {\r
-        auto moved = std::move (other);\r
-        swap (moved);\r
+        ScopedNotificationCenterObserver (std::move (other)).swap (*this);\r
         return *this;\r
     }\r
 \r
@@ -566,11 +578,13 @@ private:
         std::swap (other.observer, observer);\r
         std::swap (other.name, name);\r
         std::swap (other.object, object);\r
+        std::swap (other.klass, klass);\r
     }\r
 \r
     id observer = nullptr;\r
     NSNotificationName name = nullptr;\r
     id object = nullptr;\r
+    Class klass = nullptr;\r
 };\r
 \r
 } // namespace juce\r
index 077cce685dcc54a3a6a76e8a2803658115ddc98b..2b6939e0d1f8974e5ba074479da1717900cf7ea0 100644 (file)
@@ -135,9 +135,10 @@ SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
 \r
         case 11: return MacOS_11;\r
         case 12: return MacOS_12;\r
+        case 13: return MacOS_13;\r
     }\r
 \r
-    return UnknownOS;\r
+    return MacOSX;\r
    #endif\r
 }\r
 \r
@@ -152,6 +153,10 @@ String SystemStats::getOperatingSystemName()
 \r
 String SystemStats::getDeviceDescription()\r
 {\r
+    if (auto* userInfo = [[NSProcessInfo processInfo] environment])\r
+        if (auto* simDeviceName = [userInfo objectForKey: @"SIMULATOR_MODEL_IDENTIFIER"])\r
+            return nsStringToJuce (simDeviceName);\r
+\r
    #if JUCE_IOS\r
     const char* name = "hw.machine";\r
    #else\r
@@ -165,22 +170,7 @@ String SystemStats::getDeviceDescription()
         HeapBlock<char> model (size);\r
 \r
         if (sysctlbyname (name, model, &size, nullptr, 0) >= 0)\r
-        {\r
-            String description (model.get());\r
-\r
-           #if JUCE_IOS\r
-            if (description == "x86_64") // running in the simulator\r
-            {\r
-                if (auto* userInfo = [[NSProcessInfo processInfo] environment])\r
-                {\r
-                    if (auto* simDeviceName = [userInfo objectForKey: @"SIMULATOR_DEVICE_NAME"])\r
-                        return nsStringToJuce (simDeviceName);\r
-                }\r
-            }\r
-          #endif\r
-\r
-            return description;\r
-        }\r
+            return String (model.get());\r
     }\r
 \r
     return {};\r
@@ -351,4 +341,34 @@ int SystemStats::getPageSize()
     return (int) NSPageSize();\r
 }\r
 \r
+String SystemStats::getUniqueDeviceID()\r
+{\r
+    static const auto deviceId = []\r
+    {\r
+        ChildProcess proc;\r
+\r
+        if (proc.start ("ioreg -rd1 -c IOPlatformExpertDevice", ChildProcess::wantStdOut))\r
+        {\r
+            constexpr const char key[] = "\"IOPlatformUUID\"";\r
+            constexpr const auto keyLen = (int) sizeof (key);\r
+\r
+            auto output = proc.readAllProcessOutput();\r
+            auto index = output.indexOf (key);\r
+\r
+            if (index >= 0)\r
+            {\r
+                auto start = output.indexOf (index + keyLen, "\"");\r
+                auto end = output.indexOf (start + 1, "\"");\r
+                return output.substring (start + 1, end).replace("-", "");\r
+            }\r
+        }\r
+\r
+        return String();\r
+    }();\r
+\r
+    // Please tell someone at JUCE if this occurs\r
+    jassert (deviceId.isNotEmpty());\r
+    return deviceId;\r
+}\r
+\r
 } // namespace juce\r
index 9a88832a162628834293ad494afcd6b2b1a33d41..7c692be76871463a34fb8d04a1060437e0e760c6 100644 (file)
@@ -29,9 +29,139 @@ namespace juce
 */\r
 \r
 #if JUCE_IOS\r
-bool isIOSAppActive = true;\r
+ bool isIOSAppActive = true;\r
 #endif\r
 \r
+API_AVAILABLE (macos (10.10))\r
+static auto getNativeQOS (Thread::Priority priority)\r
+{\r
+    switch (priority)\r
+    {\r
+        case Thread::Priority::highest:    return QOS_CLASS_USER_INTERACTIVE;\r
+        case Thread::Priority::high:       return QOS_CLASS_USER_INITIATED;\r
+        case Thread::Priority::low:        return QOS_CLASS_UTILITY;\r
+        case Thread::Priority::background: return QOS_CLASS_BACKGROUND;\r
+        case Thread::Priority::normal:     break;\r
+    }\r
+\r
+    return QOS_CLASS_DEFAULT;\r
+}\r
+\r
+API_AVAILABLE (macos (10.10))\r
+static auto getJucePriority (qos_class_t qos)\r
+{\r
+    switch (qos)\r
+    {\r
+        case QOS_CLASS_USER_INTERACTIVE:    return Thread::Priority::highest;\r
+        case QOS_CLASS_USER_INITIATED:      return Thread::Priority::high;\r
+        case QOS_CLASS_UTILITY:             return Thread::Priority::low;\r
+        case QOS_CLASS_BACKGROUND:          return Thread::Priority::background;\r
+\r
+        case QOS_CLASS_UNSPECIFIED:\r
+        case QOS_CLASS_DEFAULT:             break;\r
+    }\r
+\r
+    return Thread::Priority::normal;\r
+}\r
+\r
+bool Thread::createNativeThread (Priority priority)\r
+{\r
+    PosixThreadAttribute attr { threadStackSize };\r
+\r
+    if (@available (macos 10.10, *))\r
+        pthread_attr_set_qos_class_np (attr.get(), getNativeQOS (priority), 0);\r
+    else\r
+        PosixSchedulerPriority::getNativeSchedulerAndPriority (realtimeOptions, priority).apply (attr);\r
+\r
+    threadId = threadHandle = makeThreadHandle (attr, this, [] (void* userData) -> void*\r
+    {\r
+        auto* myself = static_cast<Thread*> (userData);\r
+\r
+        JUCE_AUTORELEASEPOOL\r
+        {\r
+            juce_threadEntryPoint (myself);\r
+        }\r
+\r
+        return nullptr;\r
+    });\r
+\r
+    return threadId != nullptr;\r
+}\r
+\r
+void Thread::killThread()\r
+{\r
+    if (threadHandle != nullptr)\r
+        pthread_cancel ((pthread_t) threadHandle.load());\r
+}\r
+\r
+Thread::Priority Thread::getPriority() const\r
+{\r
+    jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+    if (! isRealtime())\r
+    {\r
+        if (@available (macOS 10.10, *))\r
+            return getJucePriority (qos_class_self());\r
+\r
+        // fallback for older versions of macOS\r
+        const auto min = jmax (0, sched_get_priority_min (SCHED_OTHER));\r
+        const auto max = jmax (0, sched_get_priority_max (SCHED_OTHER));\r
+\r
+        if (min != 0 && max != 0)\r
+        {\r
+            const auto native = PosixSchedulerPriority::findCurrentSchedulerAndPriority().getPriority();\r
+            const auto mapped = jmap (native, min, max, 0, 4);\r
+            return ThreadPriorities::getJucePriority (mapped);\r
+        }\r
+    }\r
+\r
+    return {};\r
+}\r
+\r
+bool Thread::setPriority (Priority priority)\r
+{\r
+    jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+    if (isRealtime())\r
+    {\r
+        // macOS/iOS needs to know how much time you need!\r
+        jassert (realtimeOptions->workDurationMs > 0);\r
+\r
+        mach_timebase_info_data_t timebase;\r
+        mach_timebase_info (&timebase);\r
+\r
+        const auto periodMs = realtimeOptions->workDurationMs;\r
+        const auto ticksPerMs = ((double) timebase.denom * 1000000.0) / (double) timebase.numer;\r
+        const auto periodTicks = (uint32_t) jmin ((double) std::numeric_limits<uint32_t>::max(), periodMs * ticksPerMs);\r
+\r
+        thread_time_constraint_policy_data_t policy;\r
+        policy.period = periodTicks;\r
+        policy.computation = jmin ((uint32_t) 50000, policy.period);\r
+        policy.constraint = policy.period;\r
+        policy.preemptible = true;\r
+\r
+        return thread_policy_set (pthread_mach_thread_np (pthread_self()),\r
+                                  THREAD_TIME_CONSTRAINT_POLICY,\r
+                                  (thread_policy_t) &policy,\r
+                                  THREAD_TIME_CONSTRAINT_POLICY_COUNT) == KERN_SUCCESS;\r
+    }\r
+\r
+    if (@available (macOS 10.10, *))\r
+        return pthread_set_qos_class_self_np (getNativeQOS (priority), 0) == 0;\r
+\r
+   #if JUCE_ARM\r
+    // M1 platforms should never reach this code!!!!!!\r
+    jassertfalse;\r
+   #endif\r
+\r
+    // Just in case older versions of macOS support SCHED_OTHER priorities.\r
+    const auto psp = PosixSchedulerPriority::getNativeSchedulerAndPriority ({}, priority);\r
+\r
+    struct sched_param param;\r
+    param.sched_priority = psp.getPriority();\r
+    return pthread_setschedparam (pthread_self(), psp.getScheduler(), &param) == 0;\r
+}\r
+\r
 //==============================================================================\r
 JUCE_API bool JUCE_CALLTYPE Process::isForegroundProcess()\r
 {\r
diff --git a/modules/juce_core/native/juce_native_ThreadPriorities.h b/modules/juce_core/native/juce_native_ThreadPriorities.h
new file mode 100644 (file)
index 0000000..3af0046
--- /dev/null
@@ -0,0 +1,109 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   The code included in this file is provided under the terms of the ISC license\r
+   http://www.isc.org/downloads/software-support-policy/isc-license. Permission\r
+   To use, copy, modify, and/or distribute this software for any purpose with or\r
+   without fee is hereby granted provided that the above copyright notice and\r
+   this permission notice appear in all copies.\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+struct ThreadPriorities\r
+{\r
+    struct Entry\r
+    {\r
+        Thread::Priority priority;\r
+        int native;\r
+    };\r
+\r
+   #if JUCE_ANDROID\r
+    enum AndroidThreadPriority\r
+    {\r
+        THREAD_PRIORITY_AUDIO          = -16,\r
+        THREAD_PRIORITY_FOREGROUND     = -2,\r
+        THREAD_PRIORITY_MORE_FAVORABLE = -1,\r
+        THREAD_PRIORITY_DEFAULT        = 0,\r
+        THREAD_PRIORITY_LESS_FAVORABLE = 1,\r
+        THREAD_PRIORITY_BACKGROUND     = 10,\r
+        THREAD_PRIORITY_LOWEST         = 19\r
+    };\r
+   #endif\r
+\r
+    inline static constexpr Entry table[]\r
+    {\r
+       #if JUCE_ANDROID\r
+        { Thread::Priority::highest,    AndroidThreadPriority::THREAD_PRIORITY_AUDIO },\r
+        { Thread::Priority::high,       AndroidThreadPriority::THREAD_PRIORITY_FOREGROUND },\r
+        { Thread::Priority::normal,     AndroidThreadPriority::THREAD_PRIORITY_DEFAULT },\r
+        { Thread::Priority::low,        AndroidThreadPriority::THREAD_PRIORITY_BACKGROUND - 5 },\r
+        { Thread::Priority::background, AndroidThreadPriority::THREAD_PRIORITY_BACKGROUND },\r
+       #endif\r
+\r
+       #if JUCE_LINUX || JUCE_BSD\r
+        { Thread::Priority::highest,    0 },\r
+        { Thread::Priority::high,       0 },\r
+        { Thread::Priority::normal,     0 },\r
+        { Thread::Priority::low,        0 },\r
+        { Thread::Priority::background, 0 },\r
+       #endif\r
+\r
+       #if JUCE_MAC || JUCE_IOS\r
+        { Thread::Priority::highest,    4 },\r
+        { Thread::Priority::high,       3 },\r
+        { Thread::Priority::normal,     2 },\r
+        { Thread::Priority::low,        1 },\r
+        { Thread::Priority::background, 0 },\r
+       #endif\r
+\r
+       #if JUCE_WINDOWS\r
+        { Thread::Priority::highest,    THREAD_PRIORITY_TIME_CRITICAL },\r
+        { Thread::Priority::high,       THREAD_PRIORITY_HIGHEST },\r
+        { Thread::Priority::normal,     THREAD_PRIORITY_NORMAL },\r
+        { Thread::Priority::low,        THREAD_PRIORITY_LOWEST },\r
+        { Thread::Priority::background, THREAD_PRIORITY_IDLE },\r
+       #endif\r
+    };\r
+\r
+    static_assert (std::size (table) == 5,\r
+                   "The platform may be unsupported or there may be a priority entry missing.");\r
+\r
+    static Thread::Priority getJucePriority (const int value)\r
+    {\r
+        const auto iter = std::min_element (std::begin (table),\r
+                                            std::end   (table),\r
+                                            [value] (const auto& a, const auto& b)\r
+                                            {\r
+                                                return std::abs (a.native - value) < std::abs (b.native - value);\r
+                                            });\r
+\r
+        jassert (iter != std::end (table));\r
+        return iter != std::end (table) ? iter->priority : Thread::Priority{};\r
+    }\r
+\r
+    static int getNativePriority (const Thread::Priority value)\r
+    {\r
+        const auto iter = std::find_if (std::begin (table),\r
+                                        std::end   (table),\r
+                                        [value] (const auto& entry) { return entry.priority == value; });\r
+\r
+        jassert (iter != std::end (table));\r
+        return iter != std::end (table) ? iter->native : 0;\r
+    }\r
+};\r
+\r
+} // namespace juce\r
index dde81fab3aca77a2710a80d36bbd0c9f22b018c5..7d0e1ba59fe177fdb79d4761028749a957a3b4bb 100644 (file)
@@ -254,8 +254,7 @@ void NamedPipe::close()
             pimpl->stopReadOperation = true;\r
 \r
             const char buffer[] { 0 };\r
-            const auto done = ::write (pimpl->pipeIn.get(), buffer, numElementsInArray (buffer));\r
-            ignoreUnused (done);\r
+            [[maybe_unused]] const auto done = ::write (pimpl->pipeIn.get(), buffer, numElementsInArray (buffer));\r
         }\r
     }\r
 \r
index 66ff9669b78222c8ba5d775ab4c8a8dd700629d3..a2649055acb6a90f8824b9742cd1dd5b7fc40849 100644 (file)
@@ -140,10 +140,9 @@ bool File::setAsCurrentWorkingDirectory() const
 \r
 //==============================================================================\r
 // The unix siginterrupt function is deprecated - this does the same job.\r
-int juce_siginterrupt (int sig, int flag)\r
+int juce_siginterrupt ([[maybe_unused]] int sig, [[maybe_unused]] int flag)\r
 {\r
    #if JUCE_WASM\r
-    ignoreUnused (sig, flag);\r
     return 0;\r
    #else\r
     #if JUCE_ANDROID\r
@@ -693,8 +692,7 @@ int File::getVolumeSerialNumber() const
 void juce_runSystemCommand (const String&);\r
 void juce_runSystemCommand (const String& command)\r
 {\r
-    int result = system (command.toUTF8());\r
-    ignoreUnused (result);\r
+    [[maybe_unused]] int result = system (command.toUTF8());\r
 }\r
 \r
 String juce_getOutputFromCommand (const String&);\r
@@ -851,98 +849,131 @@ void InterProcessLock::exit()
         pimpl.reset();\r
 }\r
 \r
-//==============================================================================\r
-#if JUCE_ANDROID\r
-extern JavaVM* androidJNIJavaVM;\r
-#endif\r
-\r
-static void* threadEntryProc (void* userData)\r
+class PosixThreadAttribute\r
 {\r
-    auto* myself = static_cast<Thread*> (userData);\r
-\r
-    JUCE_AUTORELEASEPOOL\r
+public:\r
+    explicit PosixThreadAttribute (size_t stackSize)\r
     {\r
-        juce_threadEntryPoint (myself);\r
+        if (valid)\r
+            pthread_attr_setstacksize (&attr, stackSize);\r
     }\r
 \r
-   #if JUCE_ANDROID\r
-    if (androidJNIJavaVM != nullptr)\r
+    ~PosixThreadAttribute()\r
     {\r
-        void* env = nullptr;\r
-        androidJNIJavaVM->GetEnv(&env, JNI_VERSION_1_2);\r
-\r
-        // only detach if we have actually been attached\r
-        if (env != nullptr)\r
-            androidJNIJavaVM->DetachCurrentThread();\r
+        if (valid)\r
+            pthread_attr_destroy (&attr);\r
     }\r
-   #endif\r
 \r
-    return nullptr;\r
-}\r
-\r
-#if JUCE_ANDROID && JUCE_MODULE_AVAILABLE_juce_audio_devices && (JUCE_USE_ANDROID_OPENSLES || JUCE_USE_ANDROID_OBOE)\r
- #define JUCE_ANDROID_REALTIME_THREAD_AVAILABLE 1\r
-#endif\r
+    auto* get() { return valid ? &attr : nullptr; }\r
 \r
-#if JUCE_ANDROID_REALTIME_THREAD_AVAILABLE\r
-extern pthread_t juce_createRealtimeAudioThread (void* (*entry) (void*), void* userPtr);\r
-#endif\r
+private:\r
+    pthread_attr_t attr;\r
+    bool valid { pthread_attr_init (&attr) == 0 };\r
+};\r
 \r
-void Thread::launchThread()\r
+class PosixSchedulerPriority\r
 {\r
-   #if JUCE_ANDROID\r
-    if (isAndroidRealtimeThread)\r
+public:\r
+    static PosixSchedulerPriority findCurrentSchedulerAndPriority()\r
     {\r
-       #if JUCE_ANDROID_REALTIME_THREAD_AVAILABLE\r
-        threadHandle = (void*) juce_createRealtimeAudioThread (threadEntryProc, this);\r
-        threadId = (ThreadID) threadHandle.get();\r
-\r
-        return;\r
-       #else\r
-        jassertfalse;\r
-       #endif\r
+        int scheduler{};\r
+        sched_param param{};\r
+        pthread_getschedparam (pthread_self(), &scheduler, &param);\r
+        return { scheduler, param.sched_priority };\r
     }\r
-   #endif\r
 \r
-    threadHandle = {};\r
-    pthread_t handle = {};\r
-    pthread_attr_t attr;\r
-    pthread_attr_t* attrPtr = nullptr;\r
-\r
-    if (pthread_attr_init (&attr) == 0)\r
+    static PosixSchedulerPriority getNativeSchedulerAndPriority (const Optional<Thread::RealtimeOptions>& rt,\r
+                                                                 [[maybe_unused]] Thread::Priority prio)\r
     {\r
-        attrPtr = &attr;\r
-        pthread_attr_setstacksize (attrPtr, threadStackSize);\r
-    }\r
+        const auto isRealtime = rt.hasValue();\r
+\r
+        const auto priority = [&]\r
+        {\r
+            if (isRealtime)\r
+            {\r
+                const auto min = jmax (0, sched_get_priority_min (SCHED_RR));\r
+                const auto max = jmax (1, sched_get_priority_max (SCHED_RR));\r
+\r
+                return jmap (rt->priority, 0, 10, min, max);\r
+            }\r
+\r
+            // We only use this helper if we're on an old macos/ios platform that might\r
+            // still respect legacy pthread priorities for SCHED_OTHER.\r
+            #if JUCE_MAC || JUCE_IOS\r
+             const auto min = jmax (0, sched_get_priority_min (SCHED_OTHER));\r
+             const auto max = jmax (0, sched_get_priority_max (SCHED_OTHER));\r
+\r
+             const auto p = [prio]\r
+             {\r
+                 switch (prio)\r
+                 {\r
+                     case Thread::Priority::highest:    return 4;\r
+                     case Thread::Priority::high:       return 3;\r
+                     case Thread::Priority::normal:     return 2;\r
+                     case Thread::Priority::low:        return 1;\r
+                     case Thread::Priority::background: return 0;\r
+                 }\r
+\r
+                 return 3;\r
+             }();\r
+\r
+             if (min != 0 && max != 0)\r
+                 return jmap (p, 0, 4, min, max);\r
+            #endif\r
+\r
+            return 0;\r
+        }();\r
+\r
+        #if JUCE_MAC || JUCE_IOS\r
+         const auto scheduler = SCHED_OTHER;\r
+        #elif JUCE_LINUX || JUCE_BSD\r
+         const auto backgroundSched = prio == Thread::Priority::background ? SCHED_IDLE\r
+                                                                           : SCHED_OTHER;\r
+         const auto scheduler = isRealtime ? SCHED_RR : backgroundSched;\r
+        #else\r
+         const auto scheduler = 0;\r
+        #endif\r
 \r
+         return { scheduler, priority };\r
+    }\r
 \r
-    if (pthread_create (&handle, attrPtr, threadEntryProc, this) == 0)\r
+    void apply ([[maybe_unused]] PosixThreadAttribute& attr) const\r
     {\r
-        pthread_detach (handle);\r
-        threadHandle = (void*) handle;\r
-        threadId = (ThreadID) threadHandle.get();\r
+        #if JUCE_LINUX || JUCE_BSD\r
+         const struct sched_param param { getPriority() };\r
+\r
+         pthread_attr_setinheritsched (attr.get(), PTHREAD_EXPLICIT_SCHED);\r
+         pthread_attr_setschedpolicy (attr.get(), getScheduler());\r
+         pthread_attr_setschedparam (attr.get(), &param);\r
+        #endif\r
     }\r
 \r
-    if (attrPtr != nullptr)\r
-        pthread_attr_destroy (attrPtr);\r
-}\r
+    constexpr int getScheduler() const { return scheduler; }\r
+    constexpr int  getPriority() const { return priority; }\r
 \r
-void Thread::closeThreadHandle()\r
+private:\r
+    constexpr PosixSchedulerPriority (int schedulerIn, int priorityIn)\r
+        : scheduler (schedulerIn), priority (priorityIn) {}\r
+\r
+    int scheduler;\r
+    int priority;\r
+};\r
+\r
+static void* makeThreadHandle (PosixThreadAttribute& attr, Thread* userData, void* (*threadEntryProc) (void*))\r
 {\r
-    threadId = {};\r
-    threadHandle = {};\r
+    pthread_t handle = {};\r
+\r
+    if (pthread_create (&handle, attr.get(), threadEntryProc, userData) != 0)\r
+        return nullptr;\r
+\r
+    pthread_detach (handle);\r
+    return (void*) handle;\r
 }\r
 \r
-void Thread::killThread()\r
+void Thread::closeThreadHandle()\r
 {\r
-    if (threadHandle.get() != nullptr)\r
-    {\r
-       #if JUCE_ANDROID\r
-        jassertfalse; // pthread_cancel not available!\r
-       #else\r
-        pthread_cancel ((pthread_t) threadHandle.get());\r
-       #endif\r
-    }\r
+    threadId = {};\r
+    threadHandle = nullptr;\r
 }\r
 \r
 void JUCE_CALLTYPE Thread::setCurrentThreadName (const String& name)\r
@@ -963,41 +994,6 @@ void JUCE_CALLTYPE Thread::setCurrentThreadName (const String& name)
    #endif\r
 }\r
 \r
-bool Thread::setThreadPriority (void* handle, int priority)\r
-{\r
-    constexpr auto maxInputPriority = 10;\r
-\r
-   #if JUCE_LINUX || JUCE_BSD\r
-    constexpr auto lowestRrPriority = 8;\r
-   #else\r
-    constexpr auto lowestRrPriority = 0;\r
-   #endif\r
-\r
-    struct sched_param param;\r
-    int policy;\r
-\r
-    if (handle == nullptr)\r
-        handle = (void*) pthread_self();\r
-\r
-    if (pthread_getschedparam ((pthread_t) handle, &policy, &param) != 0)\r
-        return false;\r
-\r
-    policy = priority < lowestRrPriority ? SCHED_OTHER : SCHED_RR;\r
-\r
-    const auto minPriority = sched_get_priority_min (policy);\r
-    const auto maxPriority = sched_get_priority_max (policy);\r
-\r
-    param.sched_priority = [&]\r
-    {\r
-        if (policy == SCHED_OTHER)\r
-            return 0;\r
-\r
-        return jmap (priority, lowestRrPriority, maxInputPriority, minPriority, maxPriority);\r
-    }();\r
-\r
-    return pthread_setschedparam ((pthread_t) handle, policy, &param) == 0;\r
-}\r
-\r
 Thread::ThreadID JUCE_CALLTYPE Thread::getCurrentThreadId()\r
 {\r
     return (ThreadID) pthread_self();\r
@@ -1017,7 +1013,7 @@ void JUCE_CALLTYPE Thread::yield()
  #define SUPPORT_AFFINITIES 1\r
 #endif\r
 \r
-void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (uint32 affinityMask)\r
+void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask ([[maybe_unused]] uint32 affinityMask)\r
 {\r
    #if SUPPORT_AFFINITIES\r
     cpu_set_t affinity;\r
@@ -1044,7 +1040,6 @@ void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (uint32 affinityMask)
     // affinities aren't supported because either the appropriate header files weren't found,\r
     // or the SUPPORT_AFFINITIES macro was turned off\r
     jassertfalse;\r
-    ignoreUnused (affinityMask);\r
    #endif\r
 }\r
 \r
@@ -1262,145 +1257,4 @@ bool ChildProcess::start (const StringArray& args, int streamFlags)
 \r
 #endif\r
 \r
-//==============================================================================\r
-struct HighResolutionTimer::Pimpl\r
-{\r
-    explicit Pimpl (HighResolutionTimer& t)\r
-        : owner (t)\r
-    {}\r
-\r
-    ~Pimpl()\r
-    {\r
-        jassert (periodMs == 0);\r
-        stop();\r
-    }\r
-\r
-    void start (int newPeriod)\r
-    {\r
-        if (periodMs == newPeriod)\r
-            return;\r
-\r
-        if (thread.get_id() == std::this_thread::get_id())\r
-        {\r
-            periodMs = newPeriod;\r
-            return;\r
-        }\r
-\r
-        stop();\r
-\r
-        periodMs = newPeriod;\r
-\r
-        thread = std::thread ([this, newPeriod]\r
-        {\r
-            setThisThreadToRealtime ((uint64) newPeriod);\r
-\r
-            auto lastPeriod = periodMs.load();\r
-            Clock clock (lastPeriod);\r
-\r
-            std::unique_lock<std::mutex> unique_lock (timerMutex);\r
-\r
-            while (periodMs != 0)\r
-            {\r
-                clock.next();\r
-                while (periodMs != 0 && clock.wait (stopCond, unique_lock));\r
-\r
-                if (periodMs == 0)\r
-                    break;\r
-\r
-                owner.hiResTimerCallback();\r
-\r
-                auto nextPeriod = periodMs.load();\r
-\r
-                if (lastPeriod != nextPeriod)\r
-                {\r
-                    lastPeriod = nextPeriod;\r
-                    clock = Clock (lastPeriod);\r
-                }\r
-            }\r
-\r
-            periodMs = 0;\r
-        });\r
-    }\r
-\r
-    void stop()\r
-    {\r
-        periodMs = 0;\r
-\r
-        const auto thread_id = thread.get_id();\r
-\r
-        if (thread_id == std::thread::id() || thread_id == std::this_thread::get_id())\r
-            return;\r
-\r
-        {\r
-            std::unique_lock<std::mutex> unique_lock (timerMutex);\r
-            stopCond.notify_one();\r
-        }\r
-\r
-        thread.join();\r
-    }\r
-\r
-    HighResolutionTimer& owner;\r
-    std::atomic<int> periodMs { 0 };\r
-\r
-private:\r
-    std::thread thread;\r
-    std::condition_variable stopCond;\r
-    std::mutex timerMutex;\r
-\r
-    class Clock\r
-    {\r
-    public:\r
-        explicit Clock (std::chrono::steady_clock::rep millis) noexcept\r
-            : time (std::chrono::steady_clock::now()),\r
-              delta (std::chrono::milliseconds (millis))\r
-        {}\r
-\r
-        bool wait (std::condition_variable& cond, std::unique_lock<std::mutex>& lock) noexcept\r
-        {\r
-            return cond.wait_until (lock, time) != std::cv_status::timeout;\r
-        }\r
-\r
-        void next() noexcept\r
-        {\r
-            time += delta;\r
-        }\r
-\r
-    private:\r
-        std::chrono::time_point<std::chrono::steady_clock> time;\r
-        std::chrono::steady_clock::duration delta;\r
-    };\r
-\r
-    static bool setThisThreadToRealtime (uint64 periodMs)\r
-    {\r
-        const auto thread = pthread_self();\r
-\r
-       #if JUCE_MAC || JUCE_IOS\r
-        mach_timebase_info_data_t timebase;\r
-        mach_timebase_info (&timebase);\r
-\r
-        const auto ticksPerMs = ((double) timebase.denom * 1000000.0) / (double) timebase.numer;\r
-        const auto periodTicks = (uint32_t) jmin ((double) std::numeric_limits<uint32_t>::max(), periodMs * ticksPerMs);\r
-\r
-        thread_time_constraint_policy_data_t policy;\r
-        policy.period      = periodTicks;\r
-        policy.computation = jmin ((uint32_t) 50000, policy.period);\r
-        policy.constraint  = policy.period;\r
-        policy.preemptible = true;\r
-\r
-        return thread_policy_set (pthread_mach_thread_np (thread),\r
-                                  THREAD_TIME_CONSTRAINT_POLICY,\r
-                                  (thread_policy_t) &policy,\r
-                                  THREAD_TIME_CONSTRAINT_POLICY_COUNT) == KERN_SUCCESS;\r
-\r
-       #else\r
-        ignoreUnused (periodMs);\r
-        struct sched_param param;\r
-        param.sched_priority = sched_get_priority_max (SCHED_RR);\r
-        return pthread_setschedparam (thread, SCHED_RR, &param) == 0;\r
-       #endif\r
-    }\r
-\r
-    JUCE_DECLARE_NON_COPYABLE (Pimpl)\r
-};\r
-\r
 } // namespace juce\r
index 7d93f26afbf7f1f05e271a8de97b3bc39cd7cf7d..6bc65bf22868c3df52196227a5fe66bb4137180d 100644 (file)
@@ -960,7 +960,7 @@ bool File::createShortcut (const String& description, const File& linkFileToCrea
     ComSmartPtr<IShellLink> shellLink;\r
     ComSmartPtr<IPersistFile> persistFile;\r
 \r
-    ignoreUnused (CoInitialize (nullptr));\r
+    [[maybe_unused]] const auto result = CoInitialize (nullptr);\r
 \r
     return SUCCEEDED (shellLink.CoCreateInstance (CLSID_ShellLink))\r
         && SUCCEEDED (shellLink->SetPath (getFullPathName().toWideCharPointer()))\r
index 2fa3befbe5db163c62d3a799967c1f11d68ef9af..63163d148b67d1983fb69e24c4ddca0e7ddbfb93 100644 (file)
 namespace juce\r
 {\r
 \r
-#if JUCE_MSVC && ! defined (__INTEL_COMPILER)\r
- #pragma intrinsic (__cpuid)\r
- #pragma intrinsic (__rdtsc)\r
-#endif\r
-\r
 void Logger::outputDebugString (const String& text)\r
 {\r
     OutputDebugString ((text + "\n").toWideCharPointer());\r
@@ -39,9 +34,50 @@ void Logger::outputDebugString (const String& text)
  JUCE_API void  juceDLL_free (void* block)    { std::free (block); }\r
 #endif\r
 \r
+static int findNumberOfPhysicalCores() noexcept\r
+{\r
+   #if JUCE_MINGW\r
+    // Not implemented in MinGW\r
+    jassertfalse;\r
+\r
+    return 1;\r
+   #else\r
+\r
+    DWORD bufferSize = 0;\r
+    GetLogicalProcessorInformation (nullptr, &bufferSize);\r
+\r
+    const auto numBuffers = (size_t) (bufferSize / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION));\r
+\r
+    if (numBuffers == 0)\r
+    {\r
+        jassertfalse;\r
+        return 0;\r
+    };\r
+\r
+    HeapBlock<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer (numBuffers);\r
+\r
+    if (! GetLogicalProcessorInformation (buffer, &bufferSize))\r
+    {\r
+        jassertfalse;\r
+        return 0;\r
+    }\r
+\r
+    return (int) std::count_if (buffer.get(), buffer.get() + numBuffers, [] (const auto& info)\r
+    {\r
+        return info.Relationship == RelationProcessorCore;\r
+    });\r
+\r
+   #endif // JUCE_MINGW\r
+}\r
+\r
 //==============================================================================\r
+#if JUCE_INTEL\r
+ #if JUCE_MSVC && ! defined (__INTEL_COMPILER)\r
+  #pragma intrinsic (__cpuid)\r
+  #pragma intrinsic (__rdtsc)\r
+ #endif\r
 \r
-#if JUCE_MINGW || JUCE_CLANG\r
+ #if JUCE_MINGW || JUCE_CLANG\r
 static void callCPUID (int result[4], uint32 type)\r
 {\r
   uint32 la = (uint32) result[0], lb = (uint32) result[1],\r
@@ -59,12 +95,12 @@ static void callCPUID (int result[4], uint32 type)
   result[0] = (int) la; result[1] = (int) lb;\r
   result[2] = (int) lc; result[3] = (int) ld;\r
 }\r
-#else\r
+ #else\r
 static void callCPUID (int result[4], int infoType)\r
 {\r
     __cpuid (result, infoType);\r
 }\r
-#endif\r
+ #endif\r
 \r
 String SystemStats::getCpuVendor()\r
 {\r
@@ -103,34 +139,6 @@ String SystemStats::getCpuModel()
     return String (name).trim();\r
 }\r
 \r
-static int findNumberOfPhysicalCores() noexcept\r
-{\r
-   #if JUCE_MINGW\r
-    // Not implemented in MinGW\r
-    jassertfalse;\r
-\r
-    return 1;\r
-   #else\r
-\r
-    int numPhysicalCores = 0;\r
-    DWORD bufferSize = 0;\r
-    GetLogicalProcessorInformation (nullptr, &bufferSize);\r
-\r
-    if (auto numBuffers = (size_t) (bufferSize / sizeof (SYSTEM_LOGICAL_PROCESSOR_INFORMATION)))\r
-    {\r
-        HeapBlock<SYSTEM_LOGICAL_PROCESSOR_INFORMATION> buffer (numBuffers);\r
-\r
-        if (GetLogicalProcessorInformation (buffer, &bufferSize))\r
-            for (size_t i = 0; i < numBuffers; ++i)\r
-                if (buffer[i].Relationship == RelationProcessorCore)\r
-                    ++numPhysicalCores;\r
-    }\r
-\r
-    return numPhysicalCores;\r
-   #endif // JUCE_MINGW\r
-}\r
-\r
-//==============================================================================\r
 void CPUInformation::initialise() noexcept\r
 {\r
     int info[4] = { 0 };\r
@@ -176,6 +184,49 @@ void CPUInformation::initialise() noexcept
     if (numPhysicalCPUs <= 0)\r
         numPhysicalCPUs = numLogicalCPUs;\r
 }\r
+#elif JUCE_ARM\r
+String SystemStats::getCpuVendor()\r
+{\r
+    static const auto cpuVendor = []\r
+    {\r
+        static constexpr auto* path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\VendorIdentifier";\r
+        auto vendor = RegistryKeyWrapper::getValue (path, {}, 0).trim();\r
+\r
+        return vendor.isEmpty() ? String ("Unknown Vendor") : vendor;\r
+    }();\r
+\r
+    return cpuVendor;\r
+}\r
+\r
+String SystemStats::getCpuModel()\r
+{\r
+    static const auto cpuModel = []\r
+    {\r
+        static constexpr auto* path = "HKEY_LOCAL_MACHINE\\HARDWARE\\DESCRIPTION\\System\\CentralProcessor\\0\\ProcessorNameString";\r
+        auto model = RegistryKeyWrapper::getValue (path, {}, 0).trim();\r
+\r
+        return model.isEmpty() ? String ("Unknown Model") : model;\r
+    }();\r
+\r
+    return cpuModel;\r
+}\r
+\r
+void CPUInformation::initialise() noexcept\r
+{\r
+    // Windows for arm requires at least armv7 which has neon support\r
+    hasNeon = true;\r
+\r
+    SYSTEM_INFO systemInfo;\r
+    GetNativeSystemInfo (&systemInfo);\r
+    numLogicalCPUs  = (int) systemInfo.dwNumberOfProcessors;\r
+    numPhysicalCPUs = findNumberOfPhysicalCores();\r
+\r
+    if (numPhysicalCPUs <= 0)\r
+        numPhysicalCPUs = numLogicalCPUs;\r
+}\r
+#else\r
+ #error Unknown CPU architecture type\r
+#endif\r
 \r
 #if JUCE_MSVC && JUCE_CHECK_MEMORY_LEAKS\r
 struct DebugFlagsInitialiser\r
@@ -263,7 +314,7 @@ SystemStats::OperatingSystemType SystemStats::getOperatingSystemType()
     if (major == 5 && minor == 0)      return Win2000;\r
 \r
     jassertfalse;\r
-    return UnknownOS;\r
+    return Windows;\r
 }\r
 \r
 String SystemStats::getOperatingSystemName()\r
@@ -298,6 +349,7 @@ String SystemStats::getOperatingSystemName()
         case MacOSX_10_15:      JUCE_FALLTHROUGH\r
         case MacOS_11:          JUCE_FALLTHROUGH\r
         case MacOS_12:          JUCE_FALLTHROUGH\r
+        case MacOS_13:          JUCE_FALLTHROUGH\r
 \r
         case UnknownOS:         JUCE_FALLTHROUGH\r
         case WASM:              JUCE_FALLTHROUGH\r
@@ -405,8 +457,7 @@ public:
        #endif\r
 \r
        #if JUCE_WIN32_TIMER_PERIOD > 0\r
-        auto res = timeBeginPeriod (JUCE_WIN32_TIMER_PERIOD);\r
-        ignoreUnused (res);\r
+        [[maybe_unused]] auto res = timeBeginPeriod (JUCE_WIN32_TIMER_PERIOD);\r
         jassert (res == TIMERR_NOERROR);\r
        #endif\r
 \r
@@ -441,11 +492,21 @@ double Time::getMillisecondCounterHiRes() noexcept       { return hiResCounterHa
 //==============================================================================\r
 static int64 juce_getClockCycleCounter() noexcept\r
 {\r
-   #if JUCE_MSVC\r
+ #if JUCE_MSVC\r
+  #if JUCE_INTEL\r
     // MS intrinsics version...\r
     return (int64) __rdtsc();\r
-\r
-   #elif JUCE_GCC || JUCE_CLANG\r
+  #elif JUCE_ARM\r
+   #if defined (_M_ARM)\r
+    return __rdpmccntr64();\r
+   #elif defined (_M_ARM64)\r
+    return _ReadStatusReg (ARM64_PMCCNTR_EL0);\r
+   #else\r
+    #error Unknown arm architecture\r
+   #endif\r
+  #endif\r
+ #elif JUCE_GCC || JUCE_CLANG\r
+  #if JUCE_INTEL\r
     // GNU inline asm version...\r
     unsigned int hi = 0, lo = 0;\r
 \r
@@ -461,9 +522,15 @@ static int64 juce_getClockCycleCounter() noexcept
          : "cc", "eax", "ebx", "ecx", "edx", "memory");\r
 \r
     return (int64) ((((uint64) hi) << 32) | lo);\r
-   #else\r
-    #error "unknown compiler?"\r
-   #endif\r
+  #elif JUCE_ARM\r
+    int64 retval;\r
+\r
+    __asm__ __volatile__ ("mrs %0, cntvct_el0" : "=r"(retval));\r
+    return retval;\r
+  #endif\r
+ #else\r
+  #error "unknown compiler?"\r
+ #endif\r
 }\r
 \r
 int SystemStats::getCpuSpeedInMegahertz()\r
@@ -592,4 +659,33 @@ String SystemStats::getDisplayLanguage()
     return languagesBuffer.data();\r
 }\r
 \r
+String SystemStats::getUniqueDeviceID()\r
+{\r
+    #define PROVIDER(string) (DWORD) (string[0] << 24 | string[1] << 16 | string[2] << 8 | string[3])\r
+\r
+    auto bufLen = GetSystemFirmwareTable (PROVIDER ("RSMB"), PROVIDER ("RSDT"), nullptr, 0);\r
+\r
+    if (bufLen > 0)\r
+    {\r
+        HeapBlock<uint8_t> buffer { bufLen };\r
+        GetSystemFirmwareTable (PROVIDER ("RSMB"), PROVIDER ("RSDT"), (void*) buffer.getData(), bufLen);\r
+\r
+        return [&]\r
+        {\r
+            uint64_t hash = 0;\r
+            const auto start = buffer.getData();\r
+            const auto end = start + jmin (1024, (int) bufLen);\r
+\r
+            for (auto dataPtr = start; dataPtr != end; ++dataPtr)\r
+                hash = hash * (uint64_t) 101 + *dataPtr;\r
+\r
+            return String (hash);\r
+        }();\r
+    }\r
+\r
+    // Please tell someone at JUCE if this occurs\r
+    jassertfalse;\r
+    return {};\r
+}\r
+\r
 } // namespace juce\r
index 8d15042fe5f2f84a978b07411adda270e4007ec9..590a9976bfce7eae93b280e2f8e159fe6f1fe968 100644 (file)
@@ -51,7 +51,6 @@ void CriticalSection::enter() const noexcept        { EnterCriticalSection ((CRI
 bool CriticalSection::tryEnter() const noexcept     { return TryEnterCriticalSection ((CRITICAL_SECTION*) &lock) != FALSE; }\r
 void CriticalSection::exit() const noexcept         { LeaveCriticalSection ((CRITICAL_SECTION*) &lock); }\r
 \r
-\r
 //==============================================================================\r
 static unsigned int STDMETHODCALLTYPE threadEntryProc (void* userData)\r
 {\r
@@ -65,36 +64,77 @@ static unsigned int STDMETHODCALLTYPE threadEntryProc (void* userData)
     return 0;\r
 }\r
 \r
-void Thread::launchThread()\r
+static bool setPriorityInternal (bool isRealtime, HANDLE handle, Thread::Priority priority)\r
+{\r
+    auto nativeThreadFlag = isRealtime ? THREAD_PRIORITY_TIME_CRITICAL\r
+                                       : ThreadPriorities::getNativePriority (priority);\r
+\r
+    if (isRealtime) // This should probably be a fail state too?\r
+        Process::setPriority (Process::ProcessPriority::RealtimePriority);\r
+\r
+    return SetThreadPriority (handle, nativeThreadFlag);\r
+}\r
+\r
+bool Thread::createNativeThread (Priority priority)\r
 {\r
     unsigned int newThreadId;\r
     threadHandle = (void*) _beginthreadex (nullptr, (unsigned int) threadStackSize,\r
-                                           &threadEntryProc, this, 0, &newThreadId);\r
-    threadId = (ThreadID) (pointer_sized_int) newThreadId;\r
+                                           &threadEntryProc, this, CREATE_SUSPENDED,\r
+                                           &newThreadId);\r
+\r
+    if (threadHandle != nullptr)\r
+    {\r
+        threadId = (ThreadID) (pointer_sized_int) newThreadId;\r
+\r
+        if (setPriorityInternal (isRealtime(), threadHandle, priority))\r
+        {\r
+            ResumeThread (threadHandle);\r
+            return true;\r
+        }\r
+\r
+        killThread();\r
+        closeThreadHandle();\r
+    }\r
+\r
+    return false;\r
+}\r
+\r
+Thread::Priority Thread::getPriority() const\r
+{\r
+    jassert (Thread::getCurrentThreadId() == getThreadId());\r
+\r
+    const auto native = GetThreadPriority (threadHandle);\r
+    return ThreadPriorities::getJucePriority (native);\r
+}\r
+\r
+bool Thread::setPriority (Priority priority)\r
+{\r
+    jassert (Thread::getCurrentThreadId() == getThreadId());\r
+    return setPriorityInternal (isRealtime(), this, priority);\r
 }\r
 \r
 void Thread::closeThreadHandle()\r
 {\r
-    CloseHandle ((HANDLE) threadHandle.get());\r
+    CloseHandle (threadHandle);\r
     threadId = nullptr;\r
     threadHandle = nullptr;\r
 }\r
 \r
 void Thread::killThread()\r
 {\r
-    if (threadHandle.get() != nullptr)\r
+    if (threadHandle != nullptr)\r
     {\r
        #if JUCE_DEBUG\r
         OutputDebugStringA ("** Warning - Forced thread termination **\n");\r
        #endif\r
 \r
         JUCE_BEGIN_IGNORE_WARNINGS_MSVC (6258)\r
-        TerminateThread (threadHandle.get(), 0);\r
+        TerminateThread (threadHandle, 0);\r
         JUCE_END_IGNORE_WARNINGS_MSVC\r
     }\r
 }\r
 \r
-void JUCE_CALLTYPE Thread::setCurrentThreadName (const String& name)\r
+void JUCE_CALLTYPE Thread::setCurrentThreadName ([[maybe_unused]] const String& name)\r
 {\r
    #if JUCE_DEBUG && JUCE_MSVC\r
     struct\r
@@ -119,8 +159,6 @@ void JUCE_CALLTYPE Thread::setCurrentThreadName (const String& name)
     {\r
         OutputDebugStringA ("** Warning - Encountered noncontinuable exception **\n");\r
     }\r
-   #else\r
-    ignoreUnused (name);\r
    #endif\r
 }\r
 \r
@@ -129,23 +167,6 @@ Thread::ThreadID JUCE_CALLTYPE Thread::getCurrentThreadId()
     return (ThreadID) (pointer_sized_int) GetCurrentThreadId();\r
 }\r
 \r
-bool Thread::setThreadPriority (void* handle, int priority)\r
-{\r
-    int pri = THREAD_PRIORITY_TIME_CRITICAL;\r
-\r
-    if (priority < 1)       pri = THREAD_PRIORITY_IDLE;\r
-    else if (priority < 2)  pri = THREAD_PRIORITY_LOWEST;\r
-    else if (priority < 5)  pri = THREAD_PRIORITY_BELOW_NORMAL;\r
-    else if (priority < 7)  pri = THREAD_PRIORITY_NORMAL;\r
-    else if (priority < 9)  pri = THREAD_PRIORITY_ABOVE_NORMAL;\r
-    else if (priority < 10) pri = THREAD_PRIORITY_HIGHEST;\r
-\r
-    if (handle == nullptr)\r
-        handle = GetCurrentThread();\r
-\r
-    return SetThreadPriority (handle, pri) != FALSE;\r
-}\r
-\r
 void JUCE_CALLTYPE Thread::setCurrentThreadAffinityMask (const uint32 affinityMask)\r
 {\r
     SetThreadAffinityMask (GetCurrentThread(), affinityMask);\r
@@ -217,11 +238,11 @@ void juce_repeatLastProcessPriority()
     }\r
 }\r
 \r
-void JUCE_CALLTYPE Process::setPriority (ProcessPriority prior)\r
+void JUCE_CALLTYPE Process::setPriority (ProcessPriority newPriority)\r
 {\r
-    if (lastProcessPriority != (int) prior)\r
+    if (lastProcessPriority != (int) newPriority)\r
     {\r
-        lastProcessPriority = (int) prior;\r
+        lastProcessPriority = (int) newPriority;\r
         juce_repeatLastProcessPriority();\r
     }\r
 }\r
@@ -527,56 +548,4 @@ bool ChildProcess::start (const StringArray& args, int streamFlags)
     return start (escaped.trim(), streamFlags);\r
 }\r
 \r
-//==============================================================================\r
-struct HighResolutionTimer::Pimpl\r
-{\r
-    Pimpl (HighResolutionTimer& t) noexcept  : owner (t)\r
-    {\r
-    }\r
-\r
-    ~Pimpl()\r
-    {\r
-        jassert (periodMs == 0);\r
-    }\r
-\r
-    void start (int newPeriod)\r
-    {\r
-        if (newPeriod != periodMs)\r
-        {\r
-            stop();\r
-            periodMs = newPeriod;\r
-\r
-            TIMECAPS tc;\r
-            if (timeGetDevCaps (&tc, sizeof (tc)) == TIMERR_NOERROR)\r
-            {\r
-                const int actualPeriod = jlimit ((int) tc.wPeriodMin, (int) tc.wPeriodMax, newPeriod);\r
-\r
-                timerID = timeSetEvent ((UINT) actualPeriod, tc.wPeriodMin, callbackFunction, (DWORD_PTR) this,\r
-                                        TIME_PERIODIC | TIME_CALLBACK_FUNCTION | 0x100 /*TIME_KILL_SYNCHRONOUS*/);\r
-            }\r
-        }\r
-    }\r
-\r
-    void stop()\r
-    {\r
-        periodMs = 0;\r
-        timeKillEvent (timerID);\r
-    }\r
-\r
-    HighResolutionTimer& owner;\r
-    int periodMs = 0;\r
-\r
-private:\r
-    unsigned int timerID;\r
-\r
-    static void STDMETHODCALLTYPE callbackFunction (UINT, UINT, DWORD_PTR userInfo, DWORD_PTR, DWORD_PTR)\r
-    {\r
-        if (Pimpl* const timer = reinterpret_cast<Pimpl*> (userInfo))\r
-            if (timer->periodMs != 0)\r
-                timer->owner.hiResTimerCallback();\r
-    }\r
-\r
-    JUCE_DECLARE_NON_COPYABLE (Pimpl)\r
-};\r
-\r
 } // namespace juce\r
index 0823d429e490193be4fef0d6d8944caf4492de03..c020720b2a0f6f2d204558f3b5cdab517ca6454d 100644 (file)
@@ -91,15 +91,16 @@ namespace SocketHelpers
                                : setOption (handle, IPPROTO_TCP, TCP_NODELAY, (int) 1));\r
     }\r
 \r
-    static void closeSocket (std::atomic<int>& handle, CriticalSection& readLock,\r
-                             bool isListener, int portNumber, std::atomic<bool>& connected) noexcept\r
+    static void closeSocket (std::atomic<int>& handle,\r
+                             [[maybe_unused]] CriticalSection& readLock,\r
+                             [[maybe_unused]] bool isListener,\r
+                             [[maybe_unused]] int portNumber,\r
+                             std::atomic<bool>& connected) noexcept\r
     {\r
         const auto h = (SocketHandle) handle.load();\r
         handle = -1;\r
 \r
        #if JUCE_WINDOWS\r
-        ignoreUnused (portNumber, isListener, readLock);\r
-\r
         if (h != invalidSocket || connected)\r
             closesocket (h);\r
 \r
@@ -771,11 +772,9 @@ bool DatagramSocket::setMulticastLoopbackEnabled (bool enable)
     return SocketHelpers::setOption<bool> ((SocketHandle) handle.load(), IPPROTO_IP, IP_MULTICAST_LOOP, enable);\r
 }\r
 \r
-bool DatagramSocket::setEnablePortReuse (bool enabled)\r
+bool DatagramSocket::setEnablePortReuse ([[maybe_unused]] bool enabled)\r
 {\r
-   #if JUCE_ANDROID\r
-    ignoreUnused (enabled);\r
-   #else\r
+   #if ! JUCE_ANDROID\r
     if (handle >= 0)\r
         return SocketHelpers::setOption ((SocketHandle) handle.load(),\r
                                         #if JUCE_WINDOWS || JUCE_LINUX || JUCE_BSD\r
index ce9c50305715a54d6cd64d09a4484d03fe41bae7..dd10be083e9fba0849e4a64da260b2cabe3ee175 100644 (file)
@@ -178,7 +178,15 @@ URL::URL (File localFile)
 \r
 void URL::init()\r
 {\r
-    auto i = url.indexOfChar ('?');\r
+    auto i = url.indexOfChar ('#');\r
+\r
+    if (i >= 0)\r
+    {\r
+        anchor = removeEscapeChars (url.substring (i + 1));\r
+        url = url.upToFirstOccurrenceOf ("#", false, false);\r
+    }\r
+\r
+    i = url.indexOfChar ('?');\r
 \r
     if (i >= 0)\r
     {\r
@@ -346,8 +354,21 @@ String URL::getSubPath (bool includeGetParameters) const
 \r
 String URL::getQueryString() const\r
 {\r
+    String result;\r
+\r
     if (parameterNames.size() > 0)\r
-        return "?" + URLHelpers::getMangledParameters (*this);\r
+        result += "?" + URLHelpers::getMangledParameters (*this);\r
+\r
+    if (anchor.isNotEmpty())\r
+        result += getAnchorString();\r
+\r
+    return result;\r
+}\r
+\r
+String URL::getAnchorString() const\r
+{\r
+    if (anchor.isNotEmpty())\r
+        return "#" + URL::addEscapeChars (anchor, true);\r
 \r
     return {};\r
 }\r
@@ -609,8 +630,7 @@ public:
             }\r
             else\r
             {\r
-                auto desc = [error localizedDescription];\r
-                ignoreUnused (desc);\r
+                [[maybe_unused]] auto desc = [error localizedDescription];\r
                 jassertfalse;\r
             }\r
         }\r
@@ -643,8 +663,7 @@ private:
                 return urlToUse.getLocalFile();\r
             }\r
 \r
-            auto desc = [error localizedDescription];\r
-            ignoreUnused (desc);\r
+            [[maybe_unused]] auto desc = [error localizedDescription];\r
             jassertfalse;\r
         }\r
 \r
@@ -861,6 +880,14 @@ URL URL::withParameters (const StringPairArray& parametersToAdd) const
     return u;\r
 }\r
 \r
+URL URL::withAnchor (const String& anchorToAdd) const\r
+{\r
+    auto u = *this;\r
+\r
+    u.anchor = anchorToAdd;\r
+    return u;\r
+}\r
+\r
 URL URL::withPOSTData (const String& newPostData) const\r
 {\r
     return withPOSTData (MemoryBlock (newPostData.toRawUTF8(), newPostData.getNumBytesAsUTF8()));\r
index 09a048a7152c1d26ffba505ce29e6e20385cdc36..6a399448c9c3379576bed39df4359569445e1dd1 100644 (file)
@@ -100,6 +100,11 @@ public:
     */\r
     String getQueryString() const;\r
 \r
+    /** If any anchor is set, returns URL-encoded anchor, including the "#"\r
+        prefix.\r
+    */\r
+    String getAnchorString() const;\r
+\r
     /** Returns the scheme of the URL.\r
 \r
         e.g. for "http://www.xyz.com/foobar", this will return "http" (it won't\r
@@ -144,7 +149,7 @@ public:
 \r
         @see withNewSubPath\r
     */\r
-    JUCE_NODISCARD URL withNewDomainAndPath (const String& newFullPath) const;\r
+    [[nodiscard]] URL withNewDomainAndPath (const String& newFullPath) const;\r
 \r
     /** Returns a new version of this URL with a different sub-path.\r
 \r
@@ -153,7 +158,7 @@ public:
 \r
         @see withNewDomainAndPath\r
     */\r
-    JUCE_NODISCARD URL withNewSubPath (const String& newPath) const;\r
+    [[nodiscard]] URL withNewSubPath (const String& newPath) const;\r
 \r
     /** Attempts to return a URL which is the parent folder containing this URL.\r
 \r
@@ -186,8 +191,8 @@ public:
 \r
         @see getParameterNames, getParameterValues\r
     */\r
-    JUCE_NODISCARD URL withParameter (const String& parameterName,\r
-                                      const String& parameterValue) const;\r
+    [[nodiscard]] URL withParameter (const String& parameterName,\r
+                                     const String& parameterValue) const;\r
 \r
     /** Returns a copy of this URL, with a set of GET or POST parameters added.\r
 \r
@@ -195,7 +200,11 @@ public:
 \r
         @see withParameter\r
     */\r
-    JUCE_NODISCARD URL withParameters (const StringPairArray& parametersToAdd) const;\r
+    [[nodiscard]] URL withParameters (const StringPairArray& parametersToAdd) const;\r
+\r
+    /** Returns a copy of this URL, with an anchor added to the end of the URL.\r
+    */\r
+    [[nodiscard]] URL withAnchor (const String& anchor) const;\r
 \r
     /** Returns a copy of this URL, with a file-upload type parameter added to it.\r
 \r
@@ -208,7 +217,7 @@ public:
 \r
         @see withDataToUpload\r
     */\r
-    JUCE_NODISCARD URL withFileToUpload (const String& parameterName,\r
+    [[nodiscard]] URL withFileToUpload (const String& parameterName,\r
                                          const File& fileToUpload,\r
                                          const String& mimeType) const;\r
 \r
@@ -222,7 +231,7 @@ public:
 \r
         @see withFileToUpload\r
     */\r
-    JUCE_NODISCARD URL withDataToUpload (const String& parameterName,\r
+    [[nodiscard]] URL withDataToUpload (const String& parameterName,\r
                                          const String& filename,\r
                                          const MemoryBlock& fileContentToUpload,\r
                                          const String& mimeType) const;\r
@@ -261,7 +270,7 @@ public:
         If no HTTP command is set when calling createInputStream() to read from\r
         this URL and some data has been set, it will do a POST request.\r
     */\r
-    JUCE_NODISCARD URL withPOSTData (const String& postData) const;\r
+    [[nodiscard]] URL withPOSTData (const String& postData) const;\r
 \r
     /** Returns a copy of this URL, with a block of data to send as the POST data.\r
 \r
@@ -271,7 +280,7 @@ public:
         If no HTTP command is set when calling createInputStream() to read from\r
         this URL and some data has been set, it will do a POST request.\r
     */\r
-    JUCE_NODISCARD URL withPOSTData (const MemoryBlock& postData) const;\r
+    [[nodiscard]] URL withPOSTData (const MemoryBlock& postData) const;\r
 \r
     /** Returns the data that was set using withPOSTData(). */\r
     String getPostData() const                                      { return postData.toString(); }\r
@@ -334,36 +343,36 @@ public:
 \r
             This can be useful for lengthy POST operations, so that you can provide user feedback.\r
         */\r
-        JUCE_NODISCARD InputStreamOptions withProgressCallback (std::function<bool (int bytesSent, int totalBytes)> progressCallback) const;\r
+        [[nodiscard]] InputStreamOptions withProgressCallback (std::function<bool (int bytesSent, int totalBytes)> progressCallback) const;\r
 \r
         /** A string that will be appended onto the headers that are used for the request.\r
 \r
             It must be a valid set of HTML header directives, separated by newlines.\r
         */\r
-        JUCE_NODISCARD InputStreamOptions withExtraHeaders (const String& extraHeaders) const;\r
+        [[nodiscard]] InputStreamOptions withExtraHeaders (const String& extraHeaders) const;\r
 \r
         /** Specifies a timeout for the request in milliseconds.\r
 \r
             If 0, this will use whatever default setting the OS chooses. If a negative\r
             number, it will be infinite.\r
         */\r
-        JUCE_NODISCARD InputStreamOptions withConnectionTimeoutMs (int connectionTimeoutMs) const;\r
+        [[nodiscard]] InputStreamOptions withConnectionTimeoutMs (int connectionTimeoutMs) const;\r
 \r
         /** If this is non-null, all the (key, value) pairs received as headers\r
             in the response will be stored in this array.\r
         */\r
-        JUCE_NODISCARD InputStreamOptions withResponseHeaders (StringPairArray* responseHeaders) const;\r
+        [[nodiscard]] InputStreamOptions withResponseHeaders (StringPairArray* responseHeaders) const;\r
 \r
         /** If this is non-null, it will get set to the http status code, if one\r
             is known, or 0 if a code isn't available.\r
         */\r
-        JUCE_NODISCARD InputStreamOptions withStatusCode (int* statusCode) const;\r
+        [[nodiscard]] InputStreamOptions withStatusCode (int* statusCode) const;\r
 \r
         /** Specifies the number of redirects that will be followed before returning a response.\r
 \r
             N.B. This will be ignored on Android which follows up to 5 redirects.\r
         */\r
-        JUCE_NODISCARD InputStreamOptions withNumRedirectsToFollow (int numRedirectsToFollow) const;\r
+        [[nodiscard]] InputStreamOptions withNumRedirectsToFollow (int numRedirectsToFollow) const;\r
 \r
         /** Specifies which HTTP request command to use.\r
 \r
@@ -372,7 +381,7 @@ public:
             via withPOSTData(), withFileToUpload(), or withDataToUpload(). Otherwise it\r
             will be GET.\r
         */\r
-        JUCE_NODISCARD InputStreamOptions withHttpRequestCmd (const String& httpRequestCmd) const;\r
+        [[nodiscard]] InputStreamOptions withHttpRequestCmd (const String& httpRequestCmd) const;\r
 \r
         //==============================================================================\r
         ParameterHandling getParameterHandling() const noexcept             { return parameterHandling; }\r
@@ -456,7 +465,7 @@ public:
         bool usePost = false;\r
 \r
         /** Specifies headers to add to the request. */\r
-        JUCE_NODISCARD auto withExtraHeaders (String value) const            { return with (&DownloadTaskOptions::extraHeaders, std::move (value)); }\r
+        [[nodiscard]] auto withExtraHeaders (String value) const            { return with (&DownloadTaskOptions::extraHeaders, std::move (value)); }\r
 \r
         /** On iOS, specifies the container where the downloaded file will be stored.\r
 \r
@@ -465,17 +474,17 @@ public:
 \r
             This is currently unused on other platforms.\r
         */\r
-        JUCE_NODISCARD auto withSharedContainer (String value) const         { return with (&DownloadTaskOptions::sharedContainer, std::move (value)); }\r
+        [[nodiscard]] auto withSharedContainer (String value) const         { return with (&DownloadTaskOptions::sharedContainer, std::move (value)); }\r
 \r
         /** Specifies an observer for the download task. */\r
-        JUCE_NODISCARD auto withListener (DownloadTaskListener* value) const { return with (&DownloadTaskOptions::listener, std::move (value)); }\r
+        [[nodiscard]] auto withListener (DownloadTaskListener* value) const { return with (&DownloadTaskOptions::listener, std::move (value)); }\r
 \r
         /** Specifies whether a post command should be used. */\r
-        JUCE_NODISCARD auto withUsePost (bool value) const                   { return with (&DownloadTaskOptions::usePost, value); }\r
+        [[nodiscard]] auto withUsePost (bool value) const                   { return with (&DownloadTaskOptions::usePost, value); }\r
 \r
     private:\r
         template <typename Member, typename Value>\r
-        JUCE_NODISCARD DownloadTaskOptions with (Member&& member, Value&& value) const\r
+        [[nodiscard]] DownloadTaskOptions with (Member&& member, Value&& value) const\r
         {\r
             auto copy = *this;\r
             copy.*member = std::forward<Value> (value);\r
@@ -723,6 +732,7 @@ private:
     String url;\r
     MemoryBlock postData;\r
     StringArray parameterNames, parameterValues;\r
+    String anchor;\r
 \r
     ReferenceCountedArray<Upload> filesToUpload;\r
 \r
index daffbc44283fa38787ca02db3c80ec2005e47119..1183c1bc728b0f0abf29b6e2eaf0815456f03425 100644 (file)
@@ -96,4 +96,11 @@ void WebInputStream::createHeadersAndPostData (const URL& aURL,
     aURL.createHeadersAndPostData (headers, data, addParametersToBody);\r
 }\r
 \r
+bool WebInputStream::Listener::postDataSendProgress ([[maybe_unused]] WebInputStream& request,\r
+                                                     [[maybe_unused]] int bytesSent,\r
+                                                     [[maybe_unused]] int totalBytes)\r
+{\r
+    return true;\r
+}\r
+\r
 } // namespace juce\r
index 883012129ddbcf2356463fd751d403a4ce2523b2..308adfe4e7df90ee039823eca87a5139f44fdef0 100644 (file)
@@ -107,11 +107,7 @@ class JUCE_API WebInputStream  : public InputStream
 \r
             @returns true to continue or false to cancel the upload\r
         */\r
-        virtual bool postDataSendProgress (WebInputStream& request, int bytesSent, int totalBytes)\r
-        {\r
-            ignoreUnused (request, bytesSent, totalBytes);\r
-            return true;\r
-        }\r
+        virtual bool postDataSendProgress (WebInputStream& request, int bytesSent, int totalBytes);\r
     };\r
 \r
     /** Wait until the first byte is ready for reading.\r
index e43b8465cef3dce88022792d129bfe66db3425b9..d3be4a8bbd88256bef5c7241e18c24f57f8e6d51 100644 (file)
@@ -172,15 +172,15 @@ bool MemoryOutputStream::setPosition (int64 newPosition)
 int64 MemoryOutputStream::writeFromInputStream (InputStream& source, int64 maxNumBytesToWrite)\r
 {\r
     // before writing from an input, see if we can preallocate to make it more efficient..\r
-    int64 availableData = source.getTotalLength() - source.getPosition();\r
+    const auto availableData = source.getTotalLength() - source.getPosition();\r
 \r
     if (availableData > 0)\r
     {\r
-        if (maxNumBytesToWrite > availableData || maxNumBytesToWrite < 0)\r
+        if (maxNumBytesToWrite < 0 || availableData < maxNumBytesToWrite)\r
             maxNumBytesToWrite = availableData;\r
 \r
         if (blockToUse != nullptr)\r
-            preallocate (blockToUse->getSize() + (size_t) maxNumBytesToWrite);\r
+            preallocate (position + (size_t) maxNumBytesToWrite);\r
     }\r
 \r
     return OutputStream::writeFromInputStream (source, maxNumBytesToWrite);\r
index bbe21625bc69cf65c091f692ff1a5efae1f51a7a..c1e173c50e3e85406d5dd7b6e4abe5bb74453236 100644 (file)
@@ -30,8 +30,8 @@
 // GCC\r
 #if JUCE_GCC\r
 \r
- #if (__GNUC__ * 100 + __GNUC_MINOR__) < 500\r
-  #error "JUCE requires GCC 5.0 or later"\r
+ #if (__GNUC__ * 100 + __GNUC_MINOR__) < 700\r
+  #error "JUCE requires GCC 7.0 or later"\r
  #endif\r
 \r
  #ifndef JUCE_EXCEPTIONS_DISABLED\r
@@ -49,8 +49,8 @@
 // Clang\r
 #if JUCE_CLANG\r
 \r
- #if (__clang_major__ < 3) || (__clang_major__ == 3 && __clang_minor__ < 4)\r
-  #error "JUCE requires Clang 3.4 or later"\r
+ #if (__clang_major__ < 6)\r
+  #error "JUCE requires Clang 6 or later"\r
  #endif\r
 \r
  #ifndef JUCE_COMPILER_SUPPORTS_ARC\r
@@ -87,8 +87,8 @@
 #endif\r
 \r
 //==============================================================================\r
-#if ! JUCE_CXX14_IS_AVAILABLE\r
- #error "JUCE requires C++14 or later"\r
+#if ! JUCE_CXX17_IS_AVAILABLE\r
+ #error "JUCE requires C++17 or later"\r
 #endif\r
 \r
 //==============================================================================\r
  #define JUCE_COMPILER_SUPPORTS_NOEXCEPT 1\r
  #define JUCE_DELETED_FUNCTION = delete\r
  #define JUCE_CONSTEXPR constexpr\r
-#endif\r
-\r
-#if JUCE_CXX17_IS_AVAILABLE\r
  #define JUCE_NODISCARD [[nodiscard]]\r
-#else\r
- #define JUCE_NODISCARD\r
 #endif\r
index 71611f104401613a8ca2ef148f19e32f5fe2d025..7a0714349caaa9d47e8039dd1317ba437b8b4324 100644 (file)
@@ -29,7 +29,7 @@
 */\r
 #define JUCE_MAJOR_VERSION      7\r
 #define JUCE_MINOR_VERSION      0\r
-#define JUCE_BUILDNUMBER        2\r
+#define JUCE_BUILDNUMBER        5\r
 \r
 /** Current JUCE version number.\r
 \r
@@ -43,8 +43,7 @@
 \r
 #if ! DOXYGEN\r
 #define JUCE_VERSION_ID \\r
-    volatile auto juceVersionId = "juce_version_" JUCE_STRINGIFY(JUCE_MAJOR_VERSION) "_" JUCE_STRINGIFY(JUCE_MINOR_VERSION) "_" JUCE_STRINGIFY(JUCE_BUILDNUMBER); \\r
-    ignoreUnused (juceVersionId);\r
+    [[maybe_unused]] volatile auto juceVersionId = "juce_version_" JUCE_STRINGIFY(JUCE_MAJOR_VERSION) "_" JUCE_STRINGIFY(JUCE_MINOR_VERSION) "_" JUCE_STRINGIFY(JUCE_BUILDNUMBER);\r
 #endif\r
 \r
 //==============================================================================\r
@@ -55,6 +54,7 @@
 #include <condition_variable>\r
 #include <cstddef>\r
 #include <functional>\r
+#include <future>\r
 #include <iomanip>\r
 #include <iostream>\r
 #include <limits>\r
 #include <memory>\r
 #include <mutex>\r
 #include <numeric>\r
+#include <optional>\r
 #include <queue>\r
 #include <set>\r
 #include <sstream>\r
+#include <thread>\r
 #include <typeindex>\r
 #include <unordered_map>\r
 #include <unordered_set>\r
 #include <utility>\r
 #include <vector>\r
-#include <set>\r
 \r
 //==============================================================================\r
 #include "juce_CompilerSupport.h"\r
index 3fe9ac7fa6b86bb2c6b8999f84d505edadc9de88..8601bc084935c7a5d74df8d18f23de524685b207 100644 (file)
@@ -253,4 +253,25 @@ bool SystemStats::isRunningInAppExtensionSandbox() noexcept
    #endif\r
 }\r
 \r
+#if JUCE_UNIT_TESTS\r
+\r
+class UniqueHardwareIDTest  : public UnitTest\r
+{\r
+public:\r
+    //==============================================================================\r
+    UniqueHardwareIDTest() : UnitTest ("UniqueHardwareID", UnitTestCategories::analytics) {}\r
+\r
+    void runTest() override\r
+    {\r
+        beginTest ("getUniqueDeviceID returns usable data.");\r
+        {\r
+            expect (SystemStats::getUniqueDeviceID().isNotEmpty());\r
+        }\r
+    }\r
+};\r
+\r
+static UniqueHardwareIDTest uniqueHardwareIDTest;\r
+\r
+#endif\r
+\r
 } // namespace juce\r
index 37924f085737ff668aea9890652e1e9eabe7bd7e..a80cc541de728eca90468349a6a867f42cfa0d22 100644 (file)
@@ -64,6 +64,7 @@ public:
         MacOSX_10_15    = MacOSX | 15,\r
         MacOS_11        = MacOSX | 16,\r
         MacOS_12        = MacOSX | 17,\r
+        MacOS_13        = MacOSX | 18,\r
 \r
         Win2000         = Windows | 1,\r
         WinXP           = Windows | 2,\r
@@ -145,8 +146,17 @@ public:
         The first choice for an ID is a filesystem ID for the user's home folder or\r
         windows directory. If that fails then this function returns the MAC addresses.\r
     */\r
+    [[deprecated ("The identifiers produced by this function are not reliable. Use getUniqueDeviceID() instead.")]]\r
     static StringArray getDeviceIdentifiers();\r
 \r
+    /** This method returns a machine unique ID unaffected by storage or peripheral\r
+        changes.\r
+\r
+        This ID will be invalidated by changes to the motherboard and CPU on non-mobile\r
+        platforms, or resetting an Android device.\r
+    */\r
+    static String getUniqueDeviceID();\r
+\r
     //==============================================================================\r
     // CPU and memory information..\r
 \r
@@ -233,7 +243,6 @@ public:
     */\r
     static bool isRunningInAppExtensionSandbox() noexcept;\r
 \r
-\r
     //==============================================================================\r
    #ifndef DOXYGEN\r
     [[deprecated ("This method was spelt wrong! Please change your code to use getCpuSpeedInMegahertz instead.")]]\r
index aca2e65676b31b5b884f220265d221d281b17a86..a93c279677833d85d75d6417fd37adf6a0691ec8 100644 (file)
   /** If defined, this indicates that the processor is little-endian. */\r
   #define JUCE_LITTLE_ENDIAN 1\r
 \r
-  #define JUCE_INTEL 1\r
+  #if defined (_M_ARM) || defined (_M_ARM64) || defined (__arm__) || defined (__aarch64__)\r
+    #define JUCE_ARM 1\r
+  #else\r
+    #define JUCE_INTEL 1\r
+  #endif\r
 #endif\r
 \r
 //==============================================================================\r
 \r
   #if JUCE_MAC\r
     #if ! defined (MAC_OS_X_VERSION_10_14)\r
-      #error "The 10.14 SDK (Xcode 10.1+) is required to build JUCE apps. You can create apps that run on macOS 10.7+ by changing the deployment target."\r
-    #elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_7\r
-      #error "Building for OSX 10.6 is no longer supported!"\r
+      #error "The 10.14 SDK (Xcode 10.1+) is required to build JUCE apps. You can create apps that run on macOS 10.9+ by changing the deployment target."\r
+    #elif MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_9\r
+      #error "Building for OSX 10.8 and earlier is no longer supported!"\r
     #endif\r
   #endif\r
 #endif\r
index 7ab9fb03b99324cfdc010f0bda0e4d729db1c304..d53695ebfde2d68b84e981ccb16fbda7c9c94f59 100644 (file)
@@ -490,8 +490,8 @@ public:
     template <typename ResultType>\r
     struct HexParser\r
     {\r
-        static_assert (std::is_unsigned<ResultType>::value, "ResultType must be unsigned because "\r
-                                                            "left-shifting a negative value is UB");\r
+        static_assert (std::is_unsigned_v<ResultType>, "ResultType must be unsigned because "\r
+                                                       "left-shifting a negative value is UB");\r
 \r
         template <typename CharPointerType>\r
         static ResultType parse (CharPointerType t) noexcept\r
index 32790de89607fda0477237f756ef5daf2101f0ae..61198e65b657c95ce727272f01e063091305c632 100644 (file)
@@ -50,14 +50,14 @@ namespace juce
     "goodbye" = "au revoir"\r
     @endcode\r
 \r
-    If the strings need to contain a quote character, they can use `\"` instead, and\r
+    If the strings need to contain a quote character, they can use \" instead, and\r
     if the first non-whitespace character on a line isn't a quote, then it's ignored,\r
     (you can use this to add comments).\r
 \r
     Note that this is a singleton class, so don't create or destroy the object directly.\r
     There's also a TRANS(text) macro defined to make it easy to use the this.\r
 \r
-    E.g. @code\r
+    @code\r
     printSomething (TRANS("hello"));\r
     @endcode\r
 \r
index 9d5e12deeaa14a8d4eec736d35b8b56c77ae27f2..92362bced2f86f2db7c92f69ea4adce2704595ea 100644 (file)
@@ -106,9 +106,9 @@ private:
     // a block of memory here that's big enough to be used internally as a windows\r
     // CRITICAL_SECTION structure.\r
     #if JUCE_64BIT\r
-     std::aligned_storage<44, 8>::type lock;\r
+     std::aligned_storage_t<44, 8> lock;\r
     #else\r
-     std::aligned_storage<24, 8>::type lock;\r
+     std::aligned_storage_t<24, 8> lock;\r
     #endif\r
    #else\r
     mutable pthread_mutex_t lock;\r
index de0f3a7670c6da586e7bb1cf1ba814715ebcebc2..28ca899d96d6ba73652c9845446284f2b17d12e9 100644 (file)
 namespace juce\r
 {\r
 \r
-HighResolutionTimer::HighResolutionTimer() : pimpl (new Pimpl (*this)) {}\r
-HighResolutionTimer::~HighResolutionTimer()                   { stopTimer(); }\r
+class HighResolutionTimer::Pimpl : public Thread\r
+{\r
+    using steady_clock = std::chrono::steady_clock;\r
+    using milliseconds = std::chrono::milliseconds;\r
+\r
+public:\r
+    explicit Pimpl (HighResolutionTimer& ownerRef)\r
+        : Thread ("HighResolutionTimerThread"),\r
+          owner (ownerRef)\r
+    {\r
+    }\r
+\r
+    using Thread::isThreadRunning;\r
+\r
+    void start (int periodMs)\r
+    {\r
+        {\r
+            const std::scoped_lock lk { mutex };\r
+            periodMillis = periodMs;\r
+            nextTickTime = steady_clock::now() + milliseconds (periodMillis);\r
+        }\r
+\r
+        waitEvent.notify_one();\r
+\r
+        if (! isThreadRunning())\r
+            startThread (Thread::Priority::high);\r
+    }\r
+\r
+    void stop()\r
+    {\r
+        {\r
+            const std::scoped_lock lk { mutex };\r
+            periodMillis = 0;\r
+        }\r
+\r
+        waitEvent.notify_one();\r
+\r
+        if (Thread::getCurrentThreadId() != getThreadId())\r
+            stopThread (-1);\r
+    }\r
+\r
+    int getPeriod() const\r
+    {\r
+        return periodMillis;\r
+    }\r
+\r
+private:\r
+    void run() override\r
+    {\r
+        for (;;)\r
+        {\r
+            {\r
+                std::unique_lock lk { mutex };\r
 \r
-void HighResolutionTimer::startTimer (int periodMs)           { pimpl->start (jmax (1, periodMs)); }\r
-void HighResolutionTimer::stopTimer()                         { pimpl->stop(); }\r
+                if (waitEvent.wait_until (lk, nextTickTime, [this] { return periodMillis == 0; }))\r
+                    break;\r
+\r
+                nextTickTime = steady_clock::now() + milliseconds (periodMillis);\r
+            }\r
+\r
+            owner.hiResTimerCallback();\r
+        }\r
+    }\r
+\r
+    HighResolutionTimer& owner;\r
+    std::atomic<int> periodMillis { 0 };\r
+    steady_clock::time_point nextTickTime;\r
+    std::mutex mutex;\r
+    std::condition_variable waitEvent;\r
+};\r
+\r
+HighResolutionTimer::HighResolutionTimer()\r
+    : pimpl (new Pimpl (*this))\r
+{\r
+}\r
+\r
+HighResolutionTimer::~HighResolutionTimer()\r
+{\r
+    stopTimer();\r
+}\r
+\r
+void HighResolutionTimer::startTimer (int periodMs)\r
+{\r
+    pimpl->start (jmax (1, periodMs));\r
+}\r
+\r
+void HighResolutionTimer::stopTimer()\r
+{\r
+    pimpl->stop();\r
+}\r
 \r
-bool HighResolutionTimer::isTimerRunning() const noexcept     { return pimpl->periodMs != 0; }\r
-int HighResolutionTimer::getTimerInterval() const noexcept    { return pimpl->periodMs; }\r
+bool HighResolutionTimer::isTimerRunning() const noexcept     { return getTimerInterval() != 0; }\r
+int HighResolutionTimer::getTimerInterval() const noexcept    { return pimpl->getPeriod(); }\r
 \r
 } // namespace juce\r
index 29ad4fd9d604182add52bc37e7daee4fc88db858..2ac6402a93414fab46c6fb3f1f1f6cef9f43647b 100644 (file)
@@ -93,7 +93,7 @@ public:
     int getTimerInterval() const noexcept;\r
 \r
 private:\r
-    struct Pimpl;\r
+    class Pimpl;\r
     std::unique_ptr<Pimpl> pimpl;\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HighResolutionTimer)\r
index dfc0c3a23d41d223d32f192cb26e7b2baa884f30..61f2157b118cefc3ee286b676b8a2580b4a966ab 100644 (file)
@@ -50,7 +50,7 @@ public:
         @param priority     the process priority, where\r
                             0=low, 1=normal, 2=high, 3=realtime\r
     */\r
-    static void JUCE_CALLTYPE setPriority (const ProcessPriority priority);\r
+    static void JUCE_CALLTYPE setPriority (ProcessPriority priority);\r
 \r
     /** Kills the current process immediately.\r
 \r
index 6c981e0afe12d1a223ac489674bb3c16e95115c3..5b870311c4d725f5b63fb782c0abfc142972d1aa 100644 (file)
@@ -22,9 +22,9 @@
 \r
 namespace juce\r
 {\r
-\r
-Thread::Thread (const String& name, size_t stackSize)\r
-   : threadName (name), threadStackSize (stackSize)\r
+//==============================================================================\r
+Thread::Thread (const String& name, size_t stackSize) : threadName (name),\r
+                                                        threadStackSize (stackSize)\r
 {\r
 }\r
 \r
@@ -84,9 +84,11 @@ void Thread::threadEntryPoint()
     if (threadName.isNotEmpty())\r
         setCurrentThreadName (threadName);\r
 \r
+    // This 'startSuspensionEvent' protects 'threadId' which is initialised after the platform's native 'CreateThread' method.\r
+    // This ensures it has been initialised correctly before it reaches this point.\r
     if (startSuspensionEvent.wait (10000))\r
     {\r
-        jassert (getCurrentThreadId() == threadId.get());\r
+        jassert (getCurrentThreadId() == threadId);\r
 \r
         if (affinityMask != 0)\r
             setCurrentThreadAffinityMask (affinityMask);\r
@@ -119,42 +121,65 @@ void JUCE_API juce_threadEntryPoint (void* userData)
 }\r
 \r
 //==============================================================================\r
-void Thread::startThread()\r
+bool Thread::startThreadInternal (Priority threadPriority)\r
 {\r
-    const ScopedLock sl (startStopLock);\r
+    shouldExit = false;\r
 \r
-    shouldExit = 0;\r
+    // 'priority' is essentially useless on Linux as only realtime\r
+    // has any options but we need to set this here to satisfy\r
+    // later queries, otherwise we get inconsistent results across\r
+    // platforms.\r
+   #if JUCE_ANDROID || JUCE_LINUX || JUCE_BSD\r
+    priority = threadPriority;\r
+   #endif\r
 \r
-    if (threadHandle.get() == nullptr)\r
+    if (createNativeThread (threadPriority))\r
     {\r
-        launchThread();\r
-        setThreadPriority (threadHandle.get(), threadPriority);\r
         startSuspensionEvent.signal();\r
+        return true;\r
     }\r
+\r
+    return false;\r
 }\r
 \r
-void Thread::startThread (int priority)\r
+bool Thread::startThread()\r
+{\r
+    return startThread (Priority::normal);\r
+}\r
+\r
+bool Thread::startThread (Priority threadPriority)\r
 {\r
     const ScopedLock sl (startStopLock);\r
 \r
-    if (threadHandle.get() == nullptr)\r
+    if (threadHandle == nullptr)\r
     {\r
-       #if JUCE_ANDROID\r
-        isAndroidRealtimeThread = (priority == realtimeAudioPriority);\r
-       #endif\r
-\r
-        threadPriority = getAdjustedPriority (priority);\r
-        startThread();\r
+        realtimeOptions.reset();\r
+        return startThreadInternal (threadPriority);\r
     }\r
-    else\r
+\r
+    return false;\r
+}\r
+\r
+bool Thread::startRealtimeThread (const RealtimeOptions& options)\r
+{\r
+    const ScopedLock sl (startStopLock);\r
+\r
+    if (threadHandle == nullptr)\r
     {\r
-        setPriority (priority);\r
+        realtimeOptions = makeOptional (options);\r
+\r
+        if (startThreadInternal (Priority::normal))\r
+            return true;\r
+\r
+        realtimeOptions.reset();\r
     }\r
+\r
+    return false;\r
 }\r
 \r
 bool Thread::isThreadRunning() const\r
 {\r
-    return threadHandle.get() != nullptr;\r
+    return threadHandle != nullptr;\r
 }\r
 \r
 Thread* JUCE_CALLTYPE Thread::getCurrentThread()\r
@@ -164,19 +189,19 @@ Thread* JUCE_CALLTYPE Thread::getCurrentThread()
 \r
 Thread::ThreadID Thread::getThreadId() const noexcept\r
 {\r
-    return threadId.get();\r
+    return threadId;\r
 }\r
 \r
 //==============================================================================\r
 void Thread::signalThreadShouldExit()\r
 {\r
-    shouldExit = 1;\r
+    shouldExit = true;\r
     listeners.call ([] (Listener& l) { l.exitSignalSent(); });\r
 }\r
 \r
 bool Thread::threadShouldExit() const\r
 {\r
-    return shouldExit.get() != 0;\r
+    return shouldExit;\r
 }\r
 \r
 bool Thread::currentThreadShouldExit()\r
@@ -249,40 +274,9 @@ void Thread::removeListener (Listener* listener)
     listeners.remove (listener);\r
 }\r
 \r
-//==============================================================================\r
-bool Thread::setPriority (int newPriority)\r
-{\r
-    newPriority = getAdjustedPriority (newPriority);\r
-\r
-    // NB: deadlock possible if you try to set the thread prio from the thread itself,\r
-    // so using setCurrentThreadPriority instead in that case.\r
-    if (getCurrentThreadId() == getThreadId())\r
-        return setCurrentThreadPriority (newPriority);\r
-\r
-    const ScopedLock sl (startStopLock);\r
-\r
-   #if JUCE_ANDROID\r
-    bool isRealtime = (newPriority == realtimeAudioPriority);\r
-\r
-    // you cannot switch from or to an Android realtime thread once the\r
-    // thread is already running!\r
-    jassert (isThreadRunning() && (isRealtime == isAndroidRealtimeThread));\r
-\r
-    isAndroidRealtimeThread = isRealtime;\r
-   #endif\r
-\r
-    if ((! isThreadRunning()) || setThreadPriority (threadHandle.get(), newPriority))\r
-    {\r
-        threadPriority = newPriority;\r
-        return true;\r
-    }\r
-\r
-    return false;\r
-}\r
-\r
-bool Thread::setCurrentThreadPriority (const int newPriority)\r
+bool Thread::isRealtime() const\r
 {\r
-    return setThreadPriority ({}, getAdjustedPriority (newPriority));\r
+    return realtimeOptions.hasValue();\r
 }\r
 \r
 void Thread::setAffinityMask (const uint32 newAffinityMask)\r
@@ -290,11 +284,6 @@ void Thread::setAffinityMask (const uint32 newAffinityMask)
     affinityMask = newAffinityMask;\r
 }\r
 \r
-int Thread::getAdjustedPriority (int newPriority)\r
-{\r
-    return jlimit (0, 10, newPriority == realtimeAudioPriority ? 9 : newPriority);\r
-}\r
-\r
 //==============================================================================\r
 bool Thread::wait (const int timeOutMilliseconds) const\r
 {\r
@@ -309,7 +298,7 @@ void Thread::notify() const
 //==============================================================================\r
 struct LambdaThread  : public Thread\r
 {\r
-    LambdaThread (std::function<void()> f) : Thread ("anonymous"), fn (f) {}\r
+    LambdaThread (std::function<void()>&& f) : Thread ("anonymous"), fn (std::move (f)) {}\r
 \r
     void run() override\r
     {\r
@@ -322,11 +311,23 @@ struct LambdaThread  : public Thread
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LambdaThread)\r
 };\r
 \r
-void Thread::launch (std::function<void()> functionToRun)\r
+bool Thread::launch (std::function<void()> functionToRun)\r
 {\r
-    auto anon = new LambdaThread (functionToRun);\r
+    return launch (Priority::normal, std::move (functionToRun));\r
+}\r
+\r
+bool Thread::launch (Priority priority, std::function<void()> functionToRun)\r
+{\r
+    auto anon = std::make_unique<LambdaThread> (std::move (functionToRun));\r
     anon->deleteOnThreadEnd = true;\r
-    anon->startThread();\r
+\r
+    if (anon->startThread (priority))\r
+    {\r
+        anon.release();\r
+        return true;\r
+    }\r
+\r
+    return false;\r
 }\r
 \r
 //==============================================================================\r
@@ -349,7 +350,6 @@ bool JUCE_CALLTYPE Process::isRunningUnderDebugger() noexcept
     return juce_isRunningUnderDebugger();\r
 }\r
 \r
-\r
 //==============================================================================\r
 //==============================================================================\r
 #if JUCE_UNIT_TESTS\r
index 19634d678c374be4860da0b8ea995e01fffc32ed..97b66ff6fbb8e195c928428cd995991a854bc234 100644 (file)
@@ -28,8 +28,8 @@ namespace juce
     Encapsulates a thread.\r
 \r
     Subclasses derive from Thread and implement the run() method, in which they\r
-    do their business. The thread can then be started with the startThread() method\r
-    and controlled with various other methods.\r
+    do their business. The thread can then be started with the startThread() or\r
+    startRealtimeThread() methods and controlled with various other methods.\r
 \r
     This class also contains some thread-related static methods, such\r
     as sleep(), yield(), getCurrentThreadId() etc.\r
@@ -42,6 +42,46 @@ namespace juce
 class JUCE_API  Thread\r
 {\r
 public:\r
+    //==============================================================================\r
+    /** The different runtime priorities of non-realtime threads.\r
+\r
+        @see startThread\r
+    */\r
+    enum class Priority\r
+    {\r
+        /** The highest possible priority that isn't a dedicated realtime thread. */\r
+        highest     = 2,\r
+\r
+        /** Makes use of performance cores and higher clocks. */\r
+        high        = 1,\r
+\r
+        /** The OS default. It will balance out across all cores. */\r
+        normal      = 0,\r
+\r
+        /** Uses efficiency cores when possible. */\r
+        low         = -1,\r
+\r
+        /** Restricted to efficiency cores on platforms that have them. */\r
+        background  = -2\r
+    };\r
+\r
+    //==============================================================================\r
+    /** A selection of options available when creating realtime threads.\r
+\r
+        @see startRealtimeThread\r
+    */\r
+    struct RealtimeOptions\r
+    {\r
+        /** Linux only: A value with a range of 0-10, where 10 is the highest priority. */\r
+        int priority = 5;\r
+\r
+        /** iOS/macOS only: A millisecond value representing the estimated time between each\r
+                            'Thread::run' call. Your thread may be penalised if you frequently\r
+                            overrun this.\r
+        */\r
+        uint32_t workDurationMs = 0;\r
+    };\r
+\r
     //==============================================================================\r
     /**\r
         Creates a thread.\r
@@ -78,23 +118,51 @@ public:
     virtual void run() = 0;\r
 \r
     //==============================================================================\r
-    /** Starts the thread running.\r
+    /** Attempts to start a new thread with default ('Priority::normal') priority.\r
 \r
         This will cause the thread's run() method to be called by a new thread.\r
         If this thread is already running, startThread() won't do anything.\r
 \r
+        If a thread cannot be created with the requested priority, this will return false\r
+        and Thread::run() will not be called. An exception to this is the Android platform,\r
+        which always starts a thread and attempts to upgrade the thread after creation.\r
+\r
+        @returns    true if the thread started successfully. false if it was unsuccesful.\r
+\r
         @see stopThread\r
     */\r
-    void startThread();\r
+    bool startThread();\r
+\r
+    /** Attempts to start a new thread with a given priority.\r
+\r
+        This will cause the thread's run() method to be called by a new thread.\r
+        If this thread is already running, startThread() won't do anything.\r
 \r
-    /** Starts the thread with a given priority.\r
+        If a thread cannot be created with the requested priority, this will return false\r
+        and Thread::run() will not be called. An exception to this is the Android platform,\r
+        which always starts a thread and attempts to upgrade the thread after creation.\r
 \r
-        Launches the thread with a given priority, where 0 = lowest, 10 = highest.\r
-        If the thread is already running, its priority will be changed.\r
+        @param newPriority    Priority the thread should be assigned. This parameter is ignored\r
+                              on Linux.\r
 \r
-        @see startThread, setPriority, realtimeAudioPriority\r
+        @returns    true if the thread started successfully, false if it was unsuccesful.\r
+\r
+        @see startThread, setPriority, startRealtimeThread\r
     */\r
-    void startThread (int priority);\r
+    bool startThread (Priority newPriority);\r
+\r
+    /** Starts the thread with realtime performance characteristics on platforms\r
+        that support it.\r
+\r
+        You cannot change the options of a running realtime thread, nor switch\r
+        a non-realtime thread to a realtime thread. To make these changes you must\r
+        first stop the thread and then restart with different options.\r
+\r
+        @param options    Realtime options the thread should be created with.\r
+\r
+        @see startThread, RealtimeOptions\r
+    */\r
+    bool startRealtimeThread (const RealtimeOptions& options);\r
 \r
     /** Attempts to stop the thread running.\r
 \r
@@ -119,7 +187,27 @@ public:
     bool stopThread (int timeOutMilliseconds);\r
 \r
     //==============================================================================\r
-    /** Invokes a lambda or function on its own thread.\r
+    /** Invokes a lambda or function on its own thread with the default priority.\r
+\r
+        This will spin up a Thread object which calls the function and then exits.\r
+        Bear in mind that starting and stopping a thread can be a fairly heavyweight\r
+        operation, so you might prefer to use a ThreadPool if you're kicking off a lot\r
+        of short background tasks.\r
+\r
+        Also note that using an anonymous thread makes it very difficult to interrupt\r
+        the function when you need to stop it, e.g. when your app quits. So it's up to\r
+        you to deal with situations where the function may fail to stop in time.\r
+\r
+        @param functionToRun  The lambda to be called from the new Thread.\r
+\r
+        @returns    true if the thread started successfully, or false if it failed.\r
+\r
+        @see launch.\r
+    */\r
+    static bool launch (std::function<void()> functionToRun);\r
+\r
+    //==============================================================================\r
+    /** Invokes a lambda or function on its own thread with a custom priority.\r
 \r
         This will spin up a Thread object which calls the function and then exits.\r
         Bear in mind that starting and stopping a thread can be a fairly heavyweight\r
@@ -129,8 +217,13 @@ public:
         Also note that using an anonymous thread makes it very difficult to interrupt\r
         the function when you need to stop it, e.g. when your app quits. So it's up to\r
         you to deal with situations where the function may fail to stop in time.\r
+\r
+        @param priority       The priority the thread is started with.\r
+        @param functionToRun  The lambda to be called from the new Thread.\r
+\r
+        @returns    true if the thread started successfully, or false if it failed.\r
     */\r
-    static void launch (std::function<void()> functionToRun);\r
+    static bool launch (Priority priority, std::function<void()> functionToRun);\r
 \r
     //==============================================================================\r
     /** Returns true if the thread is currently active */\r
@@ -198,50 +291,8 @@ public:
     /** Removes a listener added with addListener. */\r
     void removeListener (Listener*);\r
 \r
-    //==============================================================================\r
-    /** Special realtime audio thread priority\r
-\r
-        This priority will create a high-priority thread which is best suited\r
-        for realtime audio processing.\r
-\r
-        Currently, this priority is identical to priority 9, except when building\r
-        for Android with OpenSL/Oboe support.\r
-\r
-        In this case, JUCE will ask OpenSL/Oboe to construct a super high priority thread\r
-        specifically for realtime audio processing.\r
-\r
-        Note that this priority can only be set **before** the thread has\r
-        started. Switching to this priority, or from this priority to a different\r
-        priority, is not supported under Android and will assert.\r
-\r
-        For best performance this thread should yield at regular intervals\r
-        and not call any blocking APIs.\r
-\r
-        @see startThread, setPriority, sleep, WaitableEvent\r
-     */\r
-    enum\r
-    {\r
-        realtimeAudioPriority = -1\r
-    };\r
-\r
-    /** Changes the thread's priority.\r
-\r
-        May return false if for some reason the priority can't be changed.\r
-\r
-        @param priority     the new priority, in the range 0 (lowest) to 10 (highest). A priority\r
-                            of 5 is normal.\r
-        @see realtimeAudioPriority\r
-    */\r
-    bool setPriority (int priority);\r
-\r
-    /** Changes the priority of the caller thread.\r
-\r
-        Similar to setPriority(), but this static method acts on the caller thread.\r
-        May return false if for some reason the priority can't be changed.\r
-\r
-        @see setPriority\r
-    */\r
-    static bool setCurrentThreadPriority (int priority);\r
+    /** Returns true if this Thread represents a realtime thread. */\r
+    bool isRealtime() const;\r
 \r
     //==============================================================================\r
     /** Sets the affinity mask for the thread.\r
@@ -380,34 +431,58 @@ public:
     static void initialiseJUCE (void* jniEnv, void* jContext);\r
    #endif\r
 \r
+protected:\r
+    //==============================================================================\r
+    /** Returns the current priority of this thread.\r
+\r
+        This can only be called from the target thread. Doing so from another thread\r
+        will cause an assert.\r
+\r
+        @see setPriority\r
+    */\r
+    Priority getPriority() const;\r
+\r
+    /** Attempts to set the priority for this thread. Returns true if the new priority\r
+        was set successfully, false if not.\r
+\r
+        This can only be called from the target thread. Doing so from another thread\r
+        will cause an assert.\r
+\r
+        @param newPriority The new priority to be applied to the thread. Note: This\r
+                           has no effect on Linux platforms, subsequent calls to\r
+                           'getPriority' will return this value.\r
+\r
+        @see Priority\r
+    */\r
+    bool setPriority (Priority newPriority);\r
+\r
 private:\r
     //==============================================================================\r
     const String threadName;\r
-    Atomic<void*> threadHandle { nullptr };\r
-    Atomic<ThreadID> threadId = {};\r
+    std::atomic<void*> threadHandle { nullptr };\r
+    std::atomic<ThreadID> threadId { nullptr };\r
+    Optional<RealtimeOptions> realtimeOptions = {};\r
     CriticalSection startStopLock;\r
     WaitableEvent startSuspensionEvent, defaultEvent;\r
-    int threadPriority = 5;\r
     size_t threadStackSize;\r
     uint32 affinityMask = 0;\r
     bool deleteOnThreadEnd = false;\r
-    Atomic<int32> shouldExit { 0 };\r
+    std::atomic<bool> shouldExit { false };\r
     ListenerList<Listener, Array<Listener*, CriticalSection>> listeners;\r
 \r
-   #if JUCE_ANDROID\r
-    bool isAndroidRealtimeThread = false;\r
+   #if JUCE_ANDROID || JUCE_LINUX || JUCE_BSD\r
+    std::atomic<Priority> priority;\r
    #endif\r
 \r
    #ifndef DOXYGEN\r
     friend void JUCE_API juce_threadEntryPoint (void*);\r
    #endif\r
 \r
-    void launchThread();\r
+    bool startThreadInternal (Priority);\r
+    bool createNativeThread (Priority);\r
     void closeThreadHandle();\r
     void killThread();\r
     void threadEntryPoint();\r
-    static bool setThreadPriority (void*, int);\r
-    static int getAdjustedPriority (int);\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Thread)\r
 };\r
index 9b6c446f6df9c37263d2e00fdc5b9c5992a3d07f..8639481de651b2fac96948b3e015c6ae04e6c289 100644 (file)
@@ -33,11 +33,14 @@ struct ThreadPool::ThreadPoolThread  : public Thread
     void run() override\r
     {\r
         while (! threadShouldExit())\r
+        {\r
             if (! pool.runNextJob (*this))\r
                 wait (500);\r
+        }\r
     }\r
 \r
     std::atomic<ThreadPoolJob*> currentJob { nullptr };\r
+\r
     ThreadPool& pool;\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (ThreadPoolThread)\r
@@ -90,16 +93,19 @@ ThreadPoolJob* ThreadPoolJob::getCurrentThreadPoolJob()
 }\r
 \r
 //==============================================================================\r
-ThreadPool::ThreadPool (int numThreads, size_t threadStackSize)\r
+ThreadPool::ThreadPool (int numThreads, size_t threadStackSize, Thread::Priority priority)\r
 {\r
     jassert (numThreads > 0); // not much point having a pool without any threads!\r
 \r
-    createThreads (numThreads, threadStackSize);\r
+    for (int i = jmax (1, numThreads); --i >= 0;)\r
+        threads.add (new ThreadPoolThread (*this, threadStackSize));\r
+\r
+    for (auto* t : threads)\r
+        t->startThread (priority);\r
 }\r
 \r
-ThreadPool::ThreadPool()\r
+ThreadPool::ThreadPool() : ThreadPool (SystemStats::getNumCpus(), 0, Thread::Priority::normal)\r
 {\r
-    createThreads (SystemStats::getNumCpus());\r
 }\r
 \r
 ThreadPool::~ThreadPool()\r
@@ -108,15 +114,6 @@ ThreadPool::~ThreadPool()
     stopThreads();\r
 }\r
 \r
-void ThreadPool::createThreads (int numThreads, size_t threadStackSize)\r
-{\r
-    for (int i = jmax (1, numThreads); --i >= 0;)\r
-        threads.add (new ThreadPoolThread (*this, threadStackSize));\r
-\r
-    for (auto* t : threads)\r
-        t->startThread();\r
-}\r
-\r
 void ThreadPool::stopThreads()\r
 {\r
     for (auto* t : threads)\r
@@ -330,17 +327,6 @@ StringArray ThreadPool::getNamesOfAllJobs (bool onlyReturnActiveJobs) const
     return s;\r
 }\r
 \r
-bool ThreadPool::setThreadPriorities (int newPriority)\r
-{\r
-    bool ok = true;\r
-\r
-    for (auto* t : threads)\r
-        if (! t->setPriority (newPriority))\r
-            ok = false;\r
-\r
-    return ok;\r
-}\r
-\r
 ThreadPoolJob* ThreadPool::pickNextJobToRun()\r
 {\r
     OwnedArray<ThreadPoolJob> deletionList;\r
index 64394010c1d775e4190f94886f2502a5f22811dc..779b1d02fe7622f861051ee5ceda95471689a08b 100644 (file)
@@ -164,8 +164,9 @@ public:
         @param threadStackSize  the size of the stack of each thread. If this value\r
                                 is zero then the default stack size of the OS will\r
                                 be used.\r
+        @param priority         the desired priority of each thread in the pool.\r
     */\r
-    ThreadPool (int numberOfThreads, size_t threadStackSize = 0);\r
+    ThreadPool (int numberOfThreads, size_t threadStackSize = 0, Thread::Priority priority = Thread::Priority::normal);\r
 \r
     /** Creates a thread pool with one thread per CPU core.\r
         Once you've created a pool, you can give it some jobs by calling addJob().\r
@@ -309,13 +310,6 @@ public:
     */\r
     StringArray getNamesOfAllJobs (bool onlyReturnActiveJobs) const;\r
 \r
-    /** Changes the priority of all the threads.\r
-        This will call Thread::setPriority() for each thread in the pool.\r
-        May return false if for some reason the priority can't be changed.\r
-    */\r
-    bool setThreadPriorities (int newPriority);\r
-\r
-\r
 private:\r
     //==============================================================================\r
     Array<ThreadPoolJob*> jobs;\r
@@ -330,7 +324,6 @@ private:
     bool runNextJob (ThreadPoolThread&);\r
     ThreadPoolJob* pickNextJobToRun();\r
     void addToDeleteList (OwnedArray<ThreadPoolJob>&, ThreadPoolJob*) const;\r
-    void createThreads (int numThreads, size_t threadStackSize = 0);\r
     void stopThreads();\r
 \r
     // Note that this method has changed, and no longer has a parameter to indicate\r
index 261fe8597397eca305784cd6f627a6cb87987538..67a773c29c1b85ee8f31656a377bb495f56aaaeb 100644 (file)
@@ -89,6 +89,7 @@ void TimeSliceThread::moveToFrontOfQueue (TimeSliceClient* client)
 \r
 int TimeSliceThread::getNumClients() const\r
 {\r
+    const ScopedLock sl (listLock);\r
     return clients.size();\r
 }\r
 \r
@@ -98,6 +99,12 @@ TimeSliceClient* TimeSliceThread::getClient (const int i) const
     return clients[i];\r
 }\r
 \r
+bool TimeSliceThread::contains (const TimeSliceClient* c) const\r
+{\r
+    const ScopedLock sl (listLock);\r
+    return std::any_of (clients.begin(), clients.end(), [=] (auto* registered) { return registered == c; });\r
+}\r
+\r
 //==============================================================================\r
 TimeSliceClient* TimeSliceThread::getNextClient (int index) const\r
 {\r
index fc4009adba5a7d0bb454833bcf8ea9b4fd6d99bb..e4986481fa93252af4ce0a01db62e5a55d6c6959 100644 (file)
@@ -131,6 +131,9 @@ public:
     /** Returns one of the registered clients. */\r
     TimeSliceClient* getClient (int index) const;\r
 \r
+    /** Returns true if the client is currently registered. */\r
+    bool contains (const TimeSliceClient*) const;\r
+\r
     //==============================================================================\r
    #ifndef DOXYGEN\r
     void run() override;\r
index efa17b827ad63252120bb88a727b016569ae4e64..60b1a1e9a578a1ce6bcd00d9f8064bdfaeae12f3 100644 (file)
@@ -86,7 +86,7 @@ String RelativeTime::getApproximateDescription() const
     if (weeks > 8)    return describeMonths ((weeks * 12) / 52);\r
     if (weeks > 1)    return describeWeeks (weeks);\r
 \r
-    auto days = (int) inWeeks();\r
+    auto days = (int) inDays();\r
 \r
     if (days > 1)\r
         return describeDays (days);\r
index 4846fb315b2b173f8a0a7093742e5624e6b0d7ea..c4fa4b5dfc35271685424f20a2abaa2620f606a3 100644 (file)
@@ -35,7 +35,6 @@ namespace UnitTestCategories
     static const String cryptography               { "Cryptography" };\r
     static const String dsp                        { "DSP" };\r
     static const String files                      { "Files" };\r
-    static const String function                   { "Function" };\r
     static const String graphics                   { "Graphics" };\r
     static const String gui                        { "GUI" };\r
     static const String json                       { "JSON" };\r
index 041539fb1a0fde84cf8decb2e8f3ec9d7bdcab3e..c5ddd312589a532917329ea00626ed2dc7ee8622 100644 (file)
@@ -144,8 +144,8 @@ public:
         int lineWrapLength = 60;           /**< A maximum line length before wrapping is done. (If newLineChars is nullptr, this is ignored) */\r
         const char* newLineChars = "\r\n"; /**< Allows the newline characters to be set. If you set this to nullptr, then the whole XML document will be placed on a single line. */\r
 \r
-        JUCE_NODISCARD TextFormat singleLine() const;     /**< returns a copy of this format with newLineChars set to nullptr. */\r
-        JUCE_NODISCARD TextFormat withoutHeader() const;  /**< returns a copy of this format with the addDefaultHeader flag set to false. */\r
+        [[nodiscard]] TextFormat singleLine() const;     /**< returns a copy of this format with newLineChars set to nullptr. */\r
+        [[nodiscard]] TextFormat withoutHeader() const;  /**< returns a copy of this format with the addDefaultHeader flag set to false. */\r
     };\r
 \r
     /** Returns a text version of this XML element.\r
index 150890e4e19e132bdb9438f60b5bfe2f87ba0d9d..a47e45985490f3e50d56e82e0961157a20fecd6b 100644 (file)
@@ -280,9 +280,8 @@ void BlowFish::encrypt (MemoryBlock& data) const
     auto size = data.getSize();\r
     data.setSize (size + (8u - (size % 8u)));\r
 \r
-    auto success = encrypt (data.getData(), size, data.getSize());\r
+    [[maybe_unused]] auto success = encrypt (data.getData(), size, data.getSize());\r
 \r
-    ignoreUnused (success);\r
     jassert (success >= 0);\r
 }\r
 \r
index 77fa22af5e8f2413def5a61c02e3384b76871d12..8373b1464d411335f68124912193c139415a391f 100644 (file)
 \r
   ID:                 juce_cryptography\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE cryptography classes\r
   description:        Classes for various basic cryptography functions, including RSA, Blowfish, MD5, SHA, etc.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_core\r
 \r
index 4b482629c70b1a2c680c526d827e76117aed715e..90d0d3d11ae2831dfd4e0c2752029aa4a1903423 100644 (file)
@@ -39,6 +39,7 @@
 #include "values/juce_ValueTreeSynchroniser.cpp"\r
 #include "values/juce_CachedValue.cpp"\r
 #include "undomanager/juce_UndoManager.cpp"\r
+#include "undomanager/juce_UndoableAction.cpp"\r
 #include "app_properties/juce_ApplicationProperties.cpp"\r
 #include "app_properties/juce_PropertiesFile.cpp"\r
 \r
index 3ed772b81fa4e10f7d377e2f9eeac061891eeeb2..4f9ebdf0245e04805fbe2cf4aeff732e6b566a2b 100644 (file)
 \r
   ID:                 juce_data_structures\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE data model helper classes\r
   description:        Classes for undo/redo management, and smart data structures.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_events\r
 \r
diff --git a/modules/juce_data_structures/undomanager/juce_UndoableAction.cpp b/modules/juce_data_structures/undomanager/juce_UndoableAction.cpp
new file mode 100644 (file)
index 0000000..f939626
--- /dev/null
@@ -0,0 +1,31 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
+   Agreement and JUCE Privacy Policy.\r
+\r
+   End User License Agreement: www.juce.com/juce-7-licence\r
+   Privacy Policy: www.juce.com/juce-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+UndoableAction* UndoableAction::createCoalescedAction ([[maybe_unused]] UndoableAction* nextAction)  { return nullptr; }\r
+\r
+} // namespace juce\r
index 51e495ab0ea43f49a6a978d9fe879bb8735ba43b..df868b062ee312310d1a7e06b03a4131560d39d9 100644 (file)
@@ -94,7 +94,7 @@ public:
 \r
         If it's not possible to merge the two actions, the method should return a nullptr.\r
     */\r
-    virtual UndoableAction* createCoalescedAction (UndoableAction* nextAction)  { ignoreUnused (nextAction); return nullptr; }\r
+    virtual UndoableAction* createCoalescedAction (UndoableAction* nextAction);\r
 };\r
 \r
 } // namespace juce\r
index 251d9f69b50b980d002727ec31e420009dcd8bfc..a3903d9f5841d11b851c59e06691377f3bbce990 100644 (file)
@@ -46,7 +46,7 @@ public:
 \r
     SharedObject& operator= (const SharedObject&) = delete;\r
 \r
-    ~SharedObject()\r
+    ~SharedObject() override\r
     {\r
         jassert (parent == nullptr); // this should never happen unless something isn't obeying the ref-counting!\r
 \r
@@ -873,7 +873,7 @@ ValueTree::Iterator::Iterator (const ValueTree& v, bool isEnd)
 \r
 ValueTree::Iterator& ValueTree::Iterator::operator++()\r
 {\r
-    internal = static_cast<SharedObject**> (internal) + 1;\r
+    ++internal;\r
     return *this;\r
 }\r
 \r
@@ -882,7 +882,7 @@ bool ValueTree::Iterator::operator!= (const Iterator& other) const  { return int
 \r
 ValueTree ValueTree::Iterator::operator*() const\r
 {\r
-    return ValueTree (SharedObject::Ptr (*static_cast<SharedObject**> (internal)));\r
+    return ValueTree (SharedObject::Ptr (*internal));\r
 }\r
 \r
 ValueTree::Iterator ValueTree::begin() const noexcept   { return Iterator (*this, false); }\r
index d262e09c4805d053f45003f2af06ea94e7aa756d..8d147a5559cf6f3af033777e5564ff3236b0b18d 100644 (file)
@@ -70,6 +70,8 @@ namespace juce
 */\r
 class JUCE_API  ValueTree  final\r
 {\r
+    JUCE_PUBLIC_IN_DLL_BUILD (class SharedObject)\r
+\r
 public:\r
     //==============================================================================\r
     /** Creates an empty, invalid ValueTree.\r
@@ -413,7 +415,7 @@ public:
         using iterator_category  = std::forward_iterator_tag;\r
 \r
     private:\r
-        void* internal;\r
+        SharedObject** internal = nullptr;\r
     };\r
 \r
     /** Returns a start iterator for the children in this tree. */\r
@@ -614,7 +616,6 @@ public:
 \r
 private:\r
     //==============================================================================\r
-    JUCE_PUBLIC_IN_DLL_BUILD (class SharedObject)\r
     friend class SharedObject;\r
 \r
     ReferenceCountedObjectPtr<SharedObject> object;\r
index 58e1a32769fbfb6ceb63f1052e03705d99edc403..2ccf95dbd0f218deddd41f6141412716ee0f7942 100644 (file)
@@ -31,7 +31,7 @@ namespace dsp
 #ifndef DOXYGEN\r
 namespace SampleTypeHelpers // Internal classes needed for handling sample type classes\r
 {\r
-    template <typename T, bool = std::is_floating_point<T>::value>\r
+    template <typename T, bool = std::is_floating_point_v<T>>\r
     struct ElementType\r
     {\r
         using Type = T;\r
@@ -71,10 +71,10 @@ class AudioBlock
 private:\r
     template <typename OtherSampleType>\r
     using MayUseConvertingConstructor =\r
-        std::enable_if_t<std::is_same<std::remove_const_t<SampleType>,\r
-                                      std::remove_const_t<OtherSampleType>>::value\r
-                             && std::is_const<SampleType>::value\r
-                             && ! std::is_const<OtherSampleType>::value,\r
+        std::enable_if_t<std::is_same_v<std::remove_const_t<SampleType>,\r
+                                        std::remove_const_t<OtherSampleType>>\r
+                             && std::is_const_v<SampleType>\r
+                             && ! std::is_const_v<OtherSampleType>,\r
                          int>;\r
 \r
 public:\r
@@ -337,7 +337,7 @@ public:
         SIMDRegister then incrementing dstPos by one will increase the sample position\r
         in the AudioBuffer's units by a factor of SIMDRegister<SampleType>::SIMDNumElements.\r
     */\r
-    void copyTo (AudioBuffer<typename std::remove_const<NumericType>::type>& dst, size_t srcPos = 0, size_t dstPos = 0,\r
+    void copyTo (AudioBuffer<std::remove_const_t<NumericType>>& dst, size_t srcPos = 0, size_t dstPos = 0,\r
                  size_t numElements = std::numeric_limits<size_t>::max()) const\r
     {\r
         auto dstlen = static_cast<size_t> (dst.getNumSamples()) / sizeFactor;\r
@@ -518,7 +518,7 @@ public:
 \r
     //==============================================================================\r
     /** Finds the minimum and maximum value of the buffer. */\r
-    Range<typename std::remove_const<NumericType>::type> findMinAndMax() const noexcept\r
+    Range<std::remove_const_t<NumericType>> findMinAndMax() const noexcept\r
     {\r
         if (numChannels == 0)\r
             return {};\r
@@ -559,11 +559,11 @@ public:
 \r
     //==============================================================================\r
     // This class can only be used with floating point types\r
-    static_assert (std::is_same<std::remove_const_t<SampleType>, float>::value\r
-                    || std::is_same<std::remove_const_t<SampleType>, double>::value\r
+    static_assert (std::is_same_v<std::remove_const_t<SampleType>, float>\r
+                    || std::is_same_v<std::remove_const_t<SampleType>, double>\r
                   #if JUCE_USE_SIMD\r
-                    || std::is_same<std::remove_const_t<SampleType>, SIMDRegister<float>>::value\r
-                    || std::is_same<std::remove_const_t<SampleType>, SIMDRegister<double>>::value\r
+                    || std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<float>>\r
+                    || std::is_same_v<std::remove_const_t<SampleType>, SIMDRegister<double>>\r
                   #endif\r
                    , "AudioBlock only supports single or double precision floating point types");\r
 \r
index df06583cfc5886808c244c57a14e4b131a728b79..17ffad601f8c4d06f1c064ba3aa3f5c6d5f7eec6 100644 (file)
@@ -319,118 +319,110 @@ public:
 \r
 private:\r
     //==============================================================================\r
-    template <typename T>\r
-    using ScalarVoid = typename std::enable_if_t <  std::is_scalar <T>::value, void>;\r
-\r
-    template <typename T>\r
-    using SIMDVoid   = typename std::enable_if_t <! std::is_scalar <T>::value, void>;\r
-\r
-    //==============================================================================\r
-    template <typename T = SampleType>\r
-    ScalarVoid<T> copyingTests()\r
+    void copyingTests()\r
     {\r
-        auto unchangedElement1 = block.getSample (0, 4);\r
-        auto unchangedElement2 = block.getSample (1, 1);\r
+        if constexpr (std::is_scalar_v<SampleType>)\r
+        {\r
+            auto unchangedElement1 = block.getSample (0, 4);\r
+            auto unchangedElement2 = block.getSample (1, 1);\r
 \r
-        AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples);\r
+            AudioBuffer<SampleType> otherBuffer (otherData.data(), (int) otherData.size(), numSamples);\r
 \r
-        block.copyFrom (otherBuffer, 1, 2, 2);\r
+            block.copyFrom (otherBuffer, 1, 2, 2);\r
 \r
-        expectEquals (block.getSample (0, 4), unchangedElement1);\r
-        expectEquals (block.getSample (1, 1), unchangedElement2);\r
-        expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1));\r
-        expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2));\r
+            expectEquals (block.getSample (0, 4), unchangedElement1);\r
+            expectEquals (block.getSample (1, 1), unchangedElement2);\r
+            expectEquals (block.getSample (0, 2), otherBuffer.getSample (0, 1));\r
+            expectEquals (block.getSample (1, 3), otherBuffer.getSample (1, 2));\r
 \r
-        resetBlocks();\r
-\r
-        unchangedElement1 = otherBuffer.getSample (0, 4);\r
-        unchangedElement2 = otherBuffer.getSample (1, 3);\r
+            resetBlocks();\r
 \r
-        block.copyTo (otherBuffer, 2, 1, 2);\r
+            unchangedElement1 = otherBuffer.getSample (0, 4);\r
+            unchangedElement2 = otherBuffer.getSample (1, 3);\r
 \r
-        expectEquals (otherBuffer.getSample (0, 4), unchangedElement1);\r
-        expectEquals (otherBuffer.getSample (1, 3), unchangedElement2);\r
-        expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2));\r
-        expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3));\r
-    }\r
+            block.copyTo (otherBuffer, 2, 1, 2);\r
 \r
-   #if JUCE_USE_SIMD\r
-    template <typename T = SampleType>\r
-    SIMDVoid<T> copyingTests()\r
-    {\r
-        auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements;\r
-        AudioBuffer<NumericType> numericData ((int) block.getNumChannels(),\r
-                                              (int) (block.getNumSamples() * numSIMDElements));\r
+            expectEquals (otherBuffer.getSample (0, 4), unchangedElement1);\r
+            expectEquals (otherBuffer.getSample (1, 3), unchangedElement2);\r
+            expectEquals (otherBuffer.getSample (0, 1), block.getSample (0, 2));\r
+            expectEquals (otherBuffer.getSample (1, 2), block.getSample (1, 3));\r
+        }\r
+       #if JUCE_USE_SIMD\r
+        else\r
+        {\r
+            auto numSIMDElements = SIMDRegister<NumericType>::SIMDNumElements;\r
+            AudioBuffer<NumericType> numericData ((int) block.getNumChannels(),\r
+                                                  (int) (block.getNumSamples() * numSIMDElements));\r
 \r
-        for (int c = 0; c < numericData.getNumChannels(); ++c)\r
-            std::fill_n (numericData.getWritePointer (c), numericData.getNumSamples(), (NumericType) 1.0);\r
+            for (int c = 0; c < numericData.getNumChannels(); ++c)\r
+                std::fill_n (numericData.getWritePointer (c), numericData.getNumSamples(), (NumericType) 1.0);\r
 \r
-        numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 0.127, (NumericType) 17.3);\r
+            numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 0.127, (NumericType) 17.3);\r
 \r
-        auto lastUnchangedIndexBeforeCopiedRange = (int) ((numSIMDElements * 2) - 1);\r
-        auto firstUnchangedIndexAfterCopiedRange = (int) ((numSIMDElements * 4) + 1);\r
-        auto unchangedElement1 = numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange);\r
-        auto unchangedElement2 = numericData.getSample (1, firstUnchangedIndexAfterCopiedRange);\r
+            auto lastUnchangedIndexBeforeCopiedRange = (int) ((numSIMDElements * 2) - 1);\r
+            auto firstUnchangedIndexAfterCopiedRange = (int) ((numSIMDElements * 4) + 1);\r
+            auto unchangedElement1 = numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange);\r
+            auto unchangedElement2 = numericData.getSample (1, firstUnchangedIndexAfterCopiedRange);\r
 \r
-        block.copyTo (numericData, 1, 2, 2);\r
+            block.copyTo (numericData, 1, 2, 2);\r
 \r
-        expectEquals (numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange), unchangedElement1);\r
-        expectEquals (numericData.getSample (1, firstUnchangedIndexAfterCopiedRange), unchangedElement2);\r
-        expect (SampleType (numericData.getSample (0, 2 * (int) numSIMDElements)) == block.getSample (0, 1));\r
-        expect (SampleType (numericData.getSample (1, 3 * (int) numSIMDElements)) == block.getSample (1, 2));\r
+            expectEquals (numericData.getSample (0, lastUnchangedIndexBeforeCopiedRange), unchangedElement1);\r
+            expectEquals (numericData.getSample (1, firstUnchangedIndexAfterCopiedRange), unchangedElement2);\r
+            expect (SampleType (numericData.getSample (0, 2 * (int) numSIMDElements)) == block.getSample (0, 1));\r
+            expect (SampleType (numericData.getSample (1, 3 * (int) numSIMDElements)) == block.getSample (1, 2));\r
 \r
-        numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7);\r
+            numericData.applyGainRamp (0, numericData.getNumSamples(), (NumericType) 15.1, (NumericType) 0.7);\r
 \r
-        auto unchangedSIMDElement1 = block.getSample (0, 1);\r
-        auto unchangedSIMDElement2 = block.getSample (1, 4);\r
+            auto unchangedSIMDElement1 = block.getSample (0, 1);\r
+            auto unchangedSIMDElement2 = block.getSample (1, 4);\r
 \r
-        block.copyFrom (numericData, 1, 2, 2);\r
+            block.copyFrom (numericData, 1, 2, 2);\r
 \r
-        expect (block.getSample (0, 1) == unchangedSIMDElement1);\r
-        expect (block.getSample (1, 4) == unchangedSIMDElement2);\r
-        expectEquals (block.getSample (0, 2).get (0), numericData.getSample (0, (int) numSIMDElements));\r
-        expectEquals (block.getSample (1, 3).get (0), numericData.getSample (1, (int) (numSIMDElements * 2)));\r
+            expect (block.getSample (0, 1) == unchangedSIMDElement1);\r
+            expect (block.getSample (1, 4) == unchangedSIMDElement2);\r
+            expectEquals (block.getSample (0, 2).get (0), numericData.getSample (0, (int) numSIMDElements));\r
+            expectEquals (block.getSample (1, 3).get (0), numericData.getSample (1, (int) (numSIMDElements * 2)));\r
 \r
-        if (numSIMDElements > 1)\r
-        {\r
-            expectEquals (block.getSample (0, 2).get (1), numericData.getSample (0, (int) (numSIMDElements + 1)));\r
-            expectEquals (block.getSample (1, 3).get (1), numericData.getSample (1, (int) ((numSIMDElements * 2) + 1)));\r
+            if (numSIMDElements > 1)\r
+            {\r
+                expectEquals (block.getSample (0, 2).get (1), numericData.getSample (0, (int) (numSIMDElements + 1)));\r
+                expectEquals (block.getSample (1, 3).get (1), numericData.getSample (1, (int) ((numSIMDElements * 2) + 1)));\r
+            }\r
         }\r
+       #endif\r
     }\r
-   #endif\r
 \r
     //==============================================================================\r
-    template <typename T = SampleType>\r
-    ScalarVoid<T> smoothedValueTests()\r
+    void smoothedValueTests()\r
     {\r
-        block.fill ((SampleType) 1.0);\r
-        SmoothedValue<SampleType> sv { (SampleType) 1.0 };\r
-        sv.reset (1, 4);\r
-        sv.setTargetValue ((SampleType) 0.0);\r
-\r
-        block.multiplyBy (sv);\r
-        expect (block.getSample (0, 2) < (SampleType) 1.0);\r
-        expect (block.getSample (1, 2) < (SampleType) 1.0);\r
-        expect (block.getSample (0, 2) > (SampleType) 0.0);\r
-        expect (block.getSample (1, 2) > (SampleType) 0.0);\r
-        expectEquals (block.getSample (0, 5), (SampleType) 0.0);\r
-        expectEquals (block.getSample (1, 5), (SampleType) 0.0);\r
-\r
-        sv.setCurrentAndTargetValue (-1.0f);\r
-        sv.setTargetValue (0.0f);\r
-        otherBlock.fill (-1.0f);\r
-        block.replaceWithProductOf (otherBlock, sv);\r
-        expect (block.getSample (0, 2) < (SampleType) 1.0);\r
-        expect (block.getSample (1, 2) < (SampleType) 1.0);\r
-        expect (block.getSample (0, 2) > (SampleType) 0.0);\r
-        expect (block.getSample (1, 2) > (SampleType) 0.0);\r
-        expectEquals (block.getSample (0, 5), (SampleType) 0.0);\r
-        expectEquals (block.getSample (1, 5), (SampleType) 0.0);\r
+        if constexpr (std::is_scalar_v<SampleType>)\r
+        {\r
+            block.fill ((SampleType) 1.0);\r
+            SmoothedValue<SampleType> sv { (SampleType) 1.0 };\r
+            sv.reset (1, 4);\r
+            sv.setTargetValue ((SampleType) 0.0);\r
+\r
+            block.multiplyBy (sv);\r
+            expect (block.getSample (0, 2) < (SampleType) 1.0);\r
+            expect (block.getSample (1, 2) < (SampleType) 1.0);\r
+            expect (block.getSample (0, 2) > (SampleType) 0.0);\r
+            expect (block.getSample (1, 2) > (SampleType) 0.0);\r
+            expectEquals (block.getSample (0, 5), (SampleType) 0.0);\r
+            expectEquals (block.getSample (1, 5), (SampleType) 0.0);\r
+\r
+            sv.setCurrentAndTargetValue (-1.0f);\r
+            sv.setTargetValue (0.0f);\r
+            otherBlock.fill (-1.0f);\r
+            block.replaceWithProductOf (otherBlock, sv);\r
+            expect (block.getSample (0, 2) < (SampleType) 1.0);\r
+            expect (block.getSample (1, 2) < (SampleType) 1.0);\r
+            expect (block.getSample (0, 2) > (SampleType) 0.0);\r
+            expect (block.getSample (1, 2) > (SampleType) 0.0);\r
+            expectEquals (block.getSample (0, 5), (SampleType) 0.0);\r
+            expectEquals (block.getSample (1, 5), (SampleType) 0.0);\r
+        }\r
     }\r
 \r
-    template <typename T = SampleType>\r
-    SIMDVoid<T> smoothedValueTests() {}\r
-\r
     //==============================================================================\r
     void resetBlocks()\r
     {\r
@@ -451,7 +443,7 @@ private:
     //==============================================================================\r
     static SampleType* allocateAlignedMemory (int numSamplesToAllocate)\r
     {\r
-        auto alignmentLowerBound = std::alignment_of<SampleType>::value;\r
+        auto alignmentLowerBound = std::alignment_of_v<SampleType>;\r
        #if ! JUCE_WINDOWS\r
         alignmentLowerBound = jmax (sizeof (void*), alignmentLowerBound);\r
        #endif\r
index 565f8658982cae2c2bd9b7e28060f3e7b5cdb872..1051e8536238ee0d872e6e40f5fee5195d4009f8 100644 (file)
@@ -56,13 +56,13 @@ namespace detail
     }\r
 \r
     template <typename Fn, typename Ret, typename... Args>\r
-    typename std::enable_if<std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args)\r
+    std::enable_if_t<std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)\r
     {\r
         (*reinterpret_cast<Fn*> (s)) (args...);\r
     }\r
 \r
     template <typename Fn, typename Ret, typename... Args>\r
-    typename std::enable_if<! std::is_same<Ret, void>::value, Ret>::type call (void* s, Args... args)\r
+    std::enable_if_t<! std::is_same_v<Ret, void>, Ret> call (void* s, Args... args)\r
     {\r
         return (*reinterpret_cast<Fn*> (s)) (std::forward<Args> (args)...);\r
     }\r
@@ -70,10 +70,9 @@ namespace detail
     template <typename Fn>\r
     void clear (void* s)\r
     {\r
-        auto& fn = *reinterpret_cast<Fn*> (s);\r
-        fn.~Fn();\r
         // I know this looks insane, for some reason MSVC 14 sometimes thinks fn is unreferenced\r
-        ignoreUnused (fn);\r
+        [[maybe_unused]] auto& fn = *reinterpret_cast<Fn*> (s);\r
+        fn.~Fn();\r
     }\r
 \r
     template <typename Fn, typename Ret, typename... Args>\r
@@ -102,16 +101,16 @@ template <size_t len, typename Ret, typename... Args>
 class FixedSizeFunction<len, Ret (Args...)>\r
 {\r
 private:\r
-    using Storage = typename std::aligned_storage<len>::type;\r
+    using Storage = std::aligned_storage_t<len>;\r
 \r
     template <typename Item>\r
-    using Decay = typename std::decay<Item>::type;\r
+    using Decay = std::decay_t<Item>;\r
 \r
     template <typename Item, typename Fn = Decay<Item>>\r
-    using IntIfValidConversion = typename std::enable_if<sizeof (Fn) <= len\r
-                                                             && alignof (Fn) <= alignof (Storage)\r
-                                                             && ! std::is_same<FixedSizeFunction, Fn>::value,\r
-                                                         int>::type;\r
+    using IntIfValidConversion = std::enable_if_t<sizeof (Fn) <= len\r
+                                                      && alignof (Fn) <= alignof (Storage)\r
+                                                      && ! std::is_same_v<FixedSizeFunction, Fn>,\r
+                                                  int>;\r
 \r
 public:\r
     /** Create an empty function. */\r
@@ -149,7 +148,7 @@ public:
     }\r
 \r
     /** Converting constructor from smaller FixedSizeFunctions. */\r
-    template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>\r
+    template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>\r
     FixedSizeFunction (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept\r
         : vtable (other.vtable)\r
     {\r
@@ -172,7 +171,7 @@ public:
     }\r
 \r
     /** Move assignment from smaller FixedSizeFunctions. */\r
-    template <size_t otherLen, typename std::enable_if<(otherLen < len), int>::type = 0>\r
+    template <size_t otherLen, std::enable_if_t<(otherLen < len), int> = 0>\r
     FixedSizeFunction& operator= (FixedSizeFunction<otherLen, Ret (Args...)>&& other) noexcept\r
     {\r
         return *this = FixedSizeFunction (std::move (other));\r
index 6c4aa84a050c24a7fcff5313a84da11cec70bde5..e81221913ac17c81f035b71a07e4ca63a802beb1 100644 (file)
@@ -334,8 +334,8 @@ public:
             bool smallCalled = false;\r
             bool largeCalled = false;\r
 \r
-            SmallFn small = [&smallCalled, a = std::array<char, 8>{}] { smallCalled = true; juce::ignoreUnused (a); };\r
-            LargeFn large = [&largeCalled, a = std::array<char, 8>{}] { largeCalled = true; juce::ignoreUnused (a); };\r
+            SmallFn small = [&smallCalled, a = std::array<char, 8>{}] { smallCalled = true; ignoreUnused (a); };\r
+            LargeFn large = [&largeCalled, a = std::array<char, 8>{}] { largeCalled = true; ignoreUnused (a); };\r
 \r
             large = std::move (small);\r
 \r
index 270193abbb3a7328a85bf951e4b78bf274473054..04449a7906c869f7fbc44866b3514a8188356fd9 100644 (file)
@@ -70,7 +70,7 @@ struct SIMDRegister
 \r
     /** The corresponding primitive integer type, for example, this will be int32_t\r
         if type is a float. */\r
-    using MaskType = typename SIMDInternal::MaskTypeFor<ElementType>::type;\r
+    using MaskType = SIMDInternal::MaskType<ElementType>;\r
 \r
     //==============================================================================\r
     // Here are some types which are needed internally\r
index f5ed7de81c1c28ee417c08ed6ea4e05fa7be5c7c..a8881fcb77400b98d3d654c046274f252f512503 100644 (file)
@@ -30,33 +30,32 @@ namespace dsp
 \r
 namespace SIMDRegister_test_internal\r
 {\r
-    template <typename type, typename = void> struct RandomPrimitive {};\r
-\r
     template <typename type>\r
-    struct RandomPrimitive<type, typename std::enable_if<std::is_floating_point<type>::value>::type>\r
+    struct RandomPrimitive\r
     {\r
         static type next (Random& random)\r
         {\r
-            return static_cast<type> (std::is_signed<type>::value ? (random.nextFloat() * 16.0) - 8.0\r
-                                                                  : (random.nextFloat() * 8.0));\r
+            if constexpr (std::is_floating_point_v<type>)\r
+            {\r
+                return static_cast<type> (std::is_signed_v<type> ? (random.nextFloat() * 16.0) - 8.0\r
+                                                                 : (random.nextFloat() * 8.0));\r
+            }\r
+            else if constexpr (std::is_integral_v<type>)\r
+            {\r
+                return static_cast<type> (random.nextInt64());\r
+            }\r
         }\r
     };\r
 \r
     template <typename type>\r
-    struct RandomPrimitive<type, typename std::enable_if<std::is_integral<type>::value>::type>\r
+    struct RandomValue\r
     {\r
         static type next (Random& random)\r
         {\r
-            return static_cast<type> (random.nextInt64());\r
+            return RandomPrimitive<type>::next (random);\r
         }\r
     };\r
 \r
-    template <typename type>\r
-    struct RandomValue\r
-    {\r
-        static type next (Random& random) { return RandomPrimitive<type>::next (random); }\r
-    };\r
-\r
     template <typename type>\r
     struct RandomValue<std::complex<type>>\r
     {\r
@@ -756,11 +755,10 @@ public:
         template <typename type>\r
         static void run (UnitTest& u, Random& random, Tag<type>)\r
         {\r
-            bool is_signed = std::is_signed<type>::value;\r
             type array [SIMDRegister<type>::SIMDNumElements];\r
 \r
-            auto value = is_signed ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0)\r
-                                   : static_cast<type> (random.nextFloat() * 8.0);\r
+            auto value = std::is_signed_v<type> ? static_cast<type> ((random.nextFloat() * 16.0) - 8.0)\r
+                                                : static_cast<type> (random.nextFloat() * 8.0);\r
 \r
             std::fill (array, array + SIMDRegister<type>::SIMDNumElements, value);\r
             SIMDRegister<type> a, b;\r
index f9b18a045535ea156f0d2f19cfb73a878e43ff7b..19c44f575e6b606fed6df5b98b7f5116414e493c 100644 (file)
@@ -184,7 +184,7 @@ public:
         stereo processing.\r
     */\r
     template <typename ProcessContext,\r
-              std::enable_if_t<std::is_same<typename ProcessContext::SampleType, float>::value, int> = 0>\r
+              std::enable_if_t<std::is_same_v<typename ProcessContext::SampleType, float>, int> = 0>\r
     void process (const ProcessContext& context) noexcept\r
     {\r
         processSamples (context.getInputBlock(), context.getOutputBlock(), context.isBypassed);\r
index 115c2c7688650a78579aae5905251758ad0fb9ef..ab676f44bbe7aa3485d5bbe9383f9b631ffb7589 100644 (file)
@@ -62,7 +62,7 @@ class ConvolutionTest  : public UnitTest
         AudioBuffer<float> result (2, length);\r
         result.clear();\r
 \r
-        auto** channels = result.getArrayOfWritePointers();\r
+        auto* const* channels = result.getArrayOfWritePointers();\r
         std::for_each (channels, channels + result.getNumChannels(), [length] (auto* channel)\r
         {\r
             std::fill (channel, channel + length, 1.0f);\r
index 40dd665f5110bb647de4dbece205c945794895da..e939a6a867743a178404523613fa0ee6343a60b2 100644 (file)
 #include "widgets/juce_Chorus.cpp"\r
 \r
 #if JUCE_USE_SIMD\r
- #if defined(__i386__) || defined(__amd64__) || defined(_M_X64) || defined(_X86_) || defined(_M_IX86)\r
+ #if JUCE_INTEL\r
   #ifdef __AVX2__\r
    #include "native/juce_avx_SIMDNativeOps.cpp"\r
   #else\r
    #include "native/juce_sse_SIMDNativeOps.cpp"\r
   #endif\r
- #elif defined(__arm__) || defined(_M_ARM) || defined (__arm64__) || defined (__aarch64__)\r
+ #elif JUCE_ARM\r
   #include "native/juce_neon_SIMDNativeOps.cpp"\r
  #else\r
   #error "SIMD register support not implemented for this platform"\r
index 17ca0c084323dd8a0c4c47e6f2c49b819fdaee88..a64e65adb4540c228abf0b68e405ac42d7e76ec6 100644 (file)
 \r
   ID:                 juce_dsp\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE DSP classes\r
   description:        Classes for audio buffer manipulation, digital audio processing, filtering, oversampling, fast math functions etc.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_audio_formats\r
   OSXFrameworks:      Accelerate\r
@@ -74,7 +74,9 @@
   #include <immintrin.h>\r
  #endif\r
 \r
-#elif defined (__ARM_NEON__) || defined (__ARM_NEON) || defined (__arm64__) || defined (__aarch64__)\r
+// it's ok to check for _M_ARM below as this is only defined on Windows for Arm 32-bit\r
+// which has a minimum requirement of armv7, which supports neon.\r
+#elif defined (__ARM_NEON__) || defined (__ARM_NEON) || defined (__arm64__) || defined (__aarch64__) || defined (_M_ARM) || defined (_M_ARM64)\r
 \r
  #ifndef JUCE_USE_SIMD\r
   #define JUCE_USE_SIMD 1\r
@@ -206,10 +208,10 @@ namespace juce
             inline void snapToZero (long double& x) noexcept            { JUCE_SNAP_TO_ZERO (x); }\r
            #endif\r
           #else\r
-            inline void snapToZero (float&       x) noexcept            { ignoreUnused (x); }\r
+            inline void snapToZero ([[maybe_unused]] float&       x) noexcept            {}\r
            #ifndef DOXYGEN\r
-            inline void snapToZero (double&      x) noexcept            { ignoreUnused (x); }\r
-            inline void snapToZero (long double& x) noexcept            { ignoreUnused (x); }\r
+            inline void snapToZero ([[maybe_unused]] double&      x) noexcept            {}\r
+            inline void snapToZero ([[maybe_unused]] long double& x) noexcept            {}\r
            #endif\r
           #endif\r
         }\r
@@ -227,7 +229,7 @@ namespace juce
   #else\r
    #include "native/juce_sse_SIMDNativeOps.h"\r
   #endif\r
- #elif defined(__arm__) || defined(_M_ARM) || defined (__arm64__) || defined (__aarch64__)\r
+ #elif JUCE_ARM\r
   #include "native/juce_neon_SIMDNativeOps.h"\r
  #else\r
   #error "SIMD register support not implemented for this platform"\r
index 2e0c72b903f0933f56527db66262dc0539c84d4a..595e02e049e953d17c6efebc6ca919737952be9a 100644 (file)
@@ -42,8 +42,10 @@ namespace SIMDInternal
     template <> struct MaskTypeFor <std::complex<float>>    { using type = uint32_t; };\r
     template <> struct MaskTypeFor <std::complex<double>>   { using type = uint64_t; };\r
 \r
-    template <typename Primitive> struct PrimitiveType                           { using type = typename std::remove_cv<Primitive>::type; };\r
-    template <typename Primitive> struct PrimitiveType<std::complex<Primitive>>  { using type = typename std::remove_cv<Primitive>::type; };\r
+    template <typename Primitive> using MaskType = typename MaskTypeFor<Primitive>::type;\r
+\r
+    template <typename Primitive> struct PrimitiveType                           { using type = std::remove_cv_t<Primitive>; };\r
+    template <typename Primitive> struct PrimitiveType<std::complex<Primitive>>  { using type = std::remove_cv_t<Primitive>; };\r
 \r
     template <int n>    struct Log2Helper    { enum { value = Log2Helper<n/2>::value + 1 }; };\r
     template <>         struct Log2Helper<1> { enum { value = 0 }; };\r
@@ -63,7 +65,7 @@ struct SIMDFallbackOps
     static constexpr size_t bits = SIMDInternal::Log2Helper<(int) n>::value;\r
 \r
     // helper types\r
-    using MaskType = typename SIMDInternal::MaskTypeFor<ScalarType>::type;\r
+    using MaskType = SIMDInternal::MaskType<ScalarType>;\r
     union UnionType     { vSIMDType v; ScalarType s[n]; };\r
     union UnionMaskType { vSIMDType v; MaskType   m[n]; };\r
 \r
index 1391e6ecb7c9fdcb7ba336f762842e476c166ad4..2cbd565d04d32404029f64ab79c55dd69e1b4542 100644 (file)
@@ -31,6 +31,11 @@ namespace juce
         DEFINE_NEON_SIMD_CONST (int32_t, float, kEvenHighBit)    = { static_cast<int32_t>(0x80000000), 0, static_cast<int32_t>(0x80000000), 0 };\r
         DEFINE_NEON_SIMD_CONST (float, float, kOne)              = { 1.0f, 1.0f, 1.0f, 1.0f };\r
 \r
+       #if JUCE_64BIT\r
+        DEFINE_NEON_SIMD_CONST (int64_t, double, kAllBitsSet)    = { -1, -1 };\r
+        DEFINE_NEON_SIMD_CONST (double, double, kOne)            = { 1.0, 1.0 };\r
+       #endif\r
+\r
         DEFINE_NEON_SIMD_CONST (int8_t, int8_t, kAllBitsSet)     = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };\r
         DEFINE_NEON_SIMD_CONST (uint8_t, uint8_t, kAllBitsSet)   = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };\r
         DEFINE_NEON_SIMD_CONST (int16_t, int16_t, kAllBitsSet)   = { -1, -1, -1, -1, -1, -1, -1, -1 };\r
index f9cca4d534337fee1fbb5135bffb58a724096b41..7f3c6660a1aa5a61bb917c6708581595dadafbff 100644 (file)
@@ -69,9 +69,9 @@ struct SIMDNativeOps<uint32_t>
     //==============================================================================\r
     static forcedinline vSIMDType expand (uint32_t s) noexcept                                  { return vdupq_n_u32 (s); }\r
     static forcedinline vSIMDType load (const uint32_t* a) noexcept                             { return vld1q_u32 (a); }\r
-    static forcedinline void store (vSIMDType value, uint32_t* a) noexcept                      { vst1q_u32 (a, value); }\r
-    static forcedinline uint32_t get (vSIMDType v, size_t i) noexcept                           { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, uint32_t s) noexcept              { v[i] = s; return v; }\r
+    static forcedinline void      store (vSIMDType value, uint32_t* a) noexcept                 { vst1q_u32 (a, value); }\r
+    static forcedinline uint32_t  get (vSIMDType v, size_t i) noexcept                          { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, uint32_t s) noexcept              { return fb::set (v, i, s); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                       { return vaddq_u32 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                       { return vsubq_u32 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                       { return vmulq_u32 (a, b); }\r
@@ -115,9 +115,9 @@ struct SIMDNativeOps<int32_t>
     //==============================================================================\r
     static forcedinline vSIMDType expand (int32_t s) noexcept                                   { return vdupq_n_s32 (s); }\r
     static forcedinline vSIMDType load (const int32_t* a) noexcept                              { return vld1q_s32 (a); }\r
-    static forcedinline void store (vSIMDType value, int32_t* a) noexcept                       { vst1q_s32 (a, value); }\r
-    static forcedinline int32_t get (vSIMDType v, size_t i) noexcept                            { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, int32_t s) noexcept               { v[i] = s; return v; }\r
+    static forcedinline void      store (vSIMDType value, int32_t* a) noexcept                  { vst1q_s32 (a, value); }\r
+    static forcedinline int32_t   get (vSIMDType v, size_t i) noexcept                          { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, int32_t s) noexcept               { return fb::set (v, i, s); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                       { return vaddq_s32 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                       { return vsubq_s32 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                       { return vmulq_s32 (a, b); }\r
@@ -162,9 +162,9 @@ struct SIMDNativeOps<int8_t>
     //==============================================================================\r
     static forcedinline vSIMDType expand (int8_t s) noexcept                                   { return vdupq_n_s8 (s); }\r
     static forcedinline vSIMDType load (const int8_t* a) noexcept                              { return vld1q_s8 (a); }\r
-    static forcedinline void store (vSIMDType value, int8_t* a) noexcept                       { vst1q_s8 (a, value); }\r
-    static forcedinline int8_t get (vSIMDType v, size_t i) noexcept                            { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, int8_t s) noexcept               { v[i] = s; return v; }\r
+    static forcedinline void      store (vSIMDType value, int8_t* a) noexcept                  { vst1q_s8 (a, value); }\r
+    static forcedinline int8_t    get (vSIMDType v, size_t i) noexcept                         { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, int8_t s) noexcept               { return fb::set (v, i, s); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                      { return vaddq_s8 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                      { return vsubq_s8 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                      { return vmulq_s8 (a, b); }\r
@@ -181,7 +181,7 @@ struct SIMDNativeOps<int8_t>
     static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept       { return (vSIMDType) vcgeq_s8 (a, b); }\r
     static forcedinline bool      allEqual (vSIMDType a, vSIMDType b) noexcept                 { return (SIMDNativeOps<int32_t>::sum ((SIMDNativeOps<int32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
     static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_s8 (a, b, c); }\r
-    static forcedinline int8_t sum (vSIMDType a) noexcept                                      { return fb::sum (a); }\r
+    static forcedinline int8_t    sum (vSIMDType a) noexcept                                   { return fb::sum (a); }\r
     static forcedinline vSIMDType truncate (vSIMDType a) noexcept                              { return a; }\r
 };\r
 \r
@@ -203,9 +203,9 @@ struct SIMDNativeOps<uint8_t>
     //==============================================================================\r
     static forcedinline vSIMDType expand (uint8_t s) noexcept                                  { return vdupq_n_u8 (s); }\r
     static forcedinline vSIMDType load (const uint8_t* a) noexcept                             { return vld1q_u8 (a); }\r
-    static forcedinline void store (vSIMDType value, uint8_t* a) noexcept                      { vst1q_u8 (a, value); }\r
-    static forcedinline uint8_t get (vSIMDType v, size_t i) noexcept                           { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, uint8_t s) noexcept              { v[i] = s; return v; }\r
+    static forcedinline void      store (vSIMDType value, uint8_t* a) noexcept                 { vst1q_u8 (a, value); }\r
+    static forcedinline uint8_t   get (vSIMDType v, size_t i) noexcept                         { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, uint8_t s) noexcept              { return fb::set (v, i, s); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                      { return vaddq_u8 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                      { return vsubq_u8 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                      { return vmulq_u8 (a, b); }\r
@@ -222,7 +222,7 @@ struct SIMDNativeOps<uint8_t>
     static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept       { return (vSIMDType) vcgeq_u8 (a, b); }\r
     static forcedinline bool      allEqual (vSIMDType a, vSIMDType b) noexcept                 { return (SIMDNativeOps<uint32_t>::sum ((SIMDNativeOps<uint32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
     static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_u8 (a, b, c); }\r
-    static forcedinline uint8_t sum (vSIMDType a) noexcept                                     { return fb::sum (a); }\r
+    static forcedinline uint8_t   sum (vSIMDType a) noexcept                                   { return fb::sum (a); }\r
     static forcedinline vSIMDType truncate (vSIMDType a) noexcept                              { return a; }\r
 };\r
 \r
@@ -244,9 +244,9 @@ struct SIMDNativeOps<int16_t>
     //==============================================================================\r
     static forcedinline vSIMDType expand (int16_t s) noexcept                                  { return vdupq_n_s16 (s); }\r
     static forcedinline vSIMDType load (const int16_t* a) noexcept                             { return vld1q_s16 (a); }\r
-    static forcedinline void store (vSIMDType value, int16_t* a) noexcept                      { vst1q_s16 (a, value); }\r
-    static forcedinline int16_t get (vSIMDType v, size_t i) noexcept                           { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, int16_t s) noexcept              { v[i] = s; return v; }\r
+    static forcedinline void      store (vSIMDType value, int16_t* a) noexcept                 { vst1q_s16 (a, value); }\r
+    static forcedinline int16_t   get (vSIMDType v, size_t i) noexcept                         { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, int16_t s) noexcept              { return fb::set (v, i, s); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                      { return vaddq_s16 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                      { return vsubq_s16 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                      { return vmulq_s16 (a, b); }\r
@@ -263,7 +263,7 @@ struct SIMDNativeOps<int16_t>
     static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept       { return (vSIMDType) vcgeq_s16 (a, b); }\r
     static forcedinline bool      allEqual (vSIMDType a, vSIMDType b) noexcept                 { return (SIMDNativeOps<int32_t>::sum ((SIMDNativeOps<int32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
     static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_s16 (a, b, c); }\r
-    static forcedinline int16_t sum (vSIMDType a) noexcept                                     { return fb::sum (a); }\r
+    static forcedinline int16_t   sum (vSIMDType a) noexcept                                   { return fb::sum (a); }\r
     static forcedinline vSIMDType truncate (vSIMDType a) noexcept                              { return a; }\r
 };\r
 \r
@@ -286,9 +286,9 @@ struct SIMDNativeOps<uint16_t>
     //==============================================================================\r
     static forcedinline vSIMDType expand (uint16_t s) noexcept                                 { return vdupq_n_u16 (s); }\r
     static forcedinline vSIMDType load (const uint16_t* a) noexcept                            { return vld1q_u16 (a); }\r
-    static forcedinline void store (vSIMDType value, uint16_t* a) noexcept                     { vst1q_u16 (a, value); }\r
-    static forcedinline uint16_t get (vSIMDType v, size_t i) noexcept                          { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, uint16_t s) noexcept             { v[i] = s; return v; }\r
+    static forcedinline void      store (vSIMDType value, uint16_t* a) noexcept                { vst1q_u16 (a, value); }\r
+    static forcedinline uint16_t  get (vSIMDType v, size_t i) noexcept                         { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, uint16_t s) noexcept             { return fb::set (v, i, s); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                      { return vaddq_u16 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                      { return vsubq_u16 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                      { return vmulq_u16 (a, b); }\r
@@ -305,7 +305,7 @@ struct SIMDNativeOps<uint16_t>
     static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept       { return (vSIMDType) vcgeq_u16 (a, b); }\r
     static forcedinline bool      allEqual (vSIMDType a, vSIMDType b) noexcept                 { return (SIMDNativeOps<uint32_t>::sum ((SIMDNativeOps<uint32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
     static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_u16 (a, b, c); }\r
-    static forcedinline uint16_t sum (vSIMDType a) noexcept                                    { return fb::sum (a); }\r
+    static forcedinline uint16_t  sum (vSIMDType a) noexcept                                   { return fb::sum (a); }\r
     static forcedinline vSIMDType truncate (vSIMDType a) noexcept                              { return a; }\r
 };\r
 \r
@@ -327,9 +327,9 @@ struct SIMDNativeOps<int64_t>
     //==============================================================================\r
     static forcedinline vSIMDType expand (int64_t s) noexcept                                  { return vdupq_n_s64 (s); }\r
     static forcedinline vSIMDType load (const int64_t* a) noexcept                             { return vld1q_s64 (a); }\r
-    static forcedinline void store (vSIMDType value, int64_t* a) noexcept                      { vst1q_s64 (a, value); }\r
-    static forcedinline int64_t get (vSIMDType v, size_t i) noexcept                           { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, int64_t s) noexcept              { v[i] = s; return v; }\r
+    static forcedinline void      store (vSIMDType value, int64_t* a) noexcept                 { vst1q_s64 (a, value); }\r
+    static forcedinline int64_t   get (vSIMDType v, size_t i) noexcept                         { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, int64_t s) noexcept              { return fb::set (v, i, s); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                      { return vaddq_s64 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                      { return vsubq_s64 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                      { return fb::mul (a, b); }\r
@@ -346,7 +346,7 @@ struct SIMDNativeOps<int64_t>
     static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept       { return fb::greaterThanOrEqual (a, b); }\r
     static forcedinline bool      allEqual (vSIMDType a, vSIMDType b) noexcept                 { return (SIMDNativeOps<int32_t>::sum ((SIMDNativeOps<int32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
     static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return fb::multiplyAdd (a, b, c); }\r
-    static forcedinline int64_t sum (vSIMDType a) noexcept                                     { return fb::sum (a); }\r
+    static forcedinline int64_t   sum (vSIMDType a) noexcept                                   { return fb::sum (a); }\r
     static forcedinline vSIMDType truncate (vSIMDType a) noexcept                              { return a; }\r
 };\r
 \r
@@ -369,9 +369,9 @@ struct SIMDNativeOps<uint64_t>
     //==============================================================================\r
     static forcedinline vSIMDType expand (uint64_t s) noexcept                                  { return vdupq_n_u64 (s); }\r
     static forcedinline vSIMDType load (const uint64_t* a) noexcept                             { return vld1q_u64 (a); }\r
-    static forcedinline void store (vSIMDType value, uint64_t* a) noexcept                      { vst1q_u64 (a, value); }\r
-    static forcedinline uint64_t get (vSIMDType v, size_t i) noexcept                           { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, uint64_t s) noexcept              { v[i] = s; return v; }\r
+    static forcedinline void      store (vSIMDType value, uint64_t* a) noexcept                 { vst1q_u64 (a, value); }\r
+    static forcedinline uint64_t  get (vSIMDType v, size_t i) noexcept                          { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, uint64_t s) noexcept              { return fb::set (v, i, s); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                       { return vaddq_u64 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                       { return vsubq_u64 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                       { return fb::mul (a, b); }\r
@@ -388,7 +388,7 @@ struct SIMDNativeOps<uint64_t>
     static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept        { return fb::greaterThanOrEqual (a, b); }\r
     static forcedinline bool      allEqual (vSIMDType a, vSIMDType b) noexcept                  { return (SIMDNativeOps<uint32_t>::sum ((SIMDNativeOps<uint32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
     static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept  { return fb::multiplyAdd (a, b, c); }\r
-    static forcedinline uint64_t sum (vSIMDType a) noexcept                                     { return fb::sum (a); }\r
+    static forcedinline uint64_t  sum (vSIMDType a) noexcept                                    { return fb::sum (a); }\r
     static forcedinline vSIMDType truncate (vSIMDType a) noexcept                               { return a; }\r
 };\r
 \r
@@ -413,9 +413,9 @@ struct SIMDNativeOps<float>
     //==============================================================================\r
     static forcedinline vSIMDType expand (float s) noexcept                                    { return vdupq_n_f32 (s); }\r
     static forcedinline vSIMDType load (const float* a) noexcept                               { return vld1q_f32 (a); }\r
-    static forcedinline float get (vSIMDType v, size_t i) noexcept                             { return v[i]; }\r
-    static forcedinline vSIMDType set (vSIMDType v, size_t i, float s) noexcept                { v[i] = s; return v; }\r
-    static forcedinline void store (vSIMDType value, float* a) noexcept                        { vst1q_f32 (a, value); }\r
+    static forcedinline float     get (vSIMDType v, size_t i) noexcept                         { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, float s) noexcept                { return fb::set (v, i, s); }\r
+    static forcedinline void      store (vSIMDType value, float* a) noexcept                   { vst1q_f32 (a, value); }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                      { return vaddq_f32 (a, b); }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                      { return vsubq_f32 (a, b); }\r
     static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                      { return vmulq_f32 (a, b); }\r
@@ -459,6 +459,47 @@ struct SIMDNativeOps<float>
 \r
     @tags{DSP}\r
 */\r
+#if JUCE_64BIT\r
+template <>\r
+struct SIMDNativeOps<double>\r
+{\r
+    //==============================================================================\r
+    using vSIMDType = float64x2_t;\r
+    using vMaskType = uint64x2_t;\r
+    using fb = SIMDFallbackOps<double, vSIMDType>;\r
+\r
+    //==============================================================================\r
+    DECLARE_NEON_SIMD_CONST (int64_t, kAllBitsSet);\r
+    DECLARE_NEON_SIMD_CONST (double, kOne);\r
+\r
+    //==============================================================================\r
+    static forcedinline vSIMDType expand (double s) noexcept                                   { return vdupq_n_f64 (s); }\r
+    static forcedinline vSIMDType load (const double* a) noexcept                              { return vld1q_f64 (a); }\r
+    static forcedinline double    get (vSIMDType v, size_t i) noexcept                         { return fb::get (v, i); }\r
+    static forcedinline vSIMDType set (vSIMDType v, size_t i, double s) noexcept               { return fb::set (v, i, s); }\r
+    static forcedinline void      store (vSIMDType value, double* a) noexcept                  { vst1q_f64 (a, value); }\r
+    static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                      { return vaddq_f64 (a, b); }\r
+    static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                      { return vsubq_f64 (a, b); }\r
+    static forcedinline vSIMDType mul (vSIMDType a, vSIMDType b) noexcept                      { return vmulq_f64 (a, b); }\r
+    static forcedinline vSIMDType bit_and (vSIMDType a, vSIMDType b) noexcept                  { return (vSIMDType) vandq_u64 ((vMaskType) a, (vMaskType) b); }\r
+    static forcedinline vSIMDType bit_or  (vSIMDType a, vSIMDType b) noexcept                  { return (vSIMDType) vorrq_u64 ((vMaskType) a, (vMaskType) b); }\r
+    static forcedinline vSIMDType bit_xor (vSIMDType a, vSIMDType b) noexcept                  { return (vSIMDType) veorq_u64 ((vMaskType) a, (vMaskType) b); }\r
+    static forcedinline vSIMDType bit_notand (vSIMDType a, vSIMDType b) noexcept               { return (vSIMDType) vbicq_u64 ((vMaskType) b, (vMaskType) a); }\r
+    static forcedinline vSIMDType bit_not (vSIMDType a) noexcept                               { return bit_notand (a, vld1q_f64 ((double*) kAllBitsSet)); }\r
+    static forcedinline vSIMDType min (vSIMDType a, vSIMDType b) noexcept                      { return vminq_f64 (a, b); }\r
+    static forcedinline vSIMDType max (vSIMDType a, vSIMDType b) noexcept                      { return vmaxq_f64 (a, b); }\r
+    static forcedinline vSIMDType equal (vSIMDType a, vSIMDType b) noexcept                    { return (vSIMDType) vceqq_f64 (a, b); }\r
+    static forcedinline vSIMDType notEqual (vSIMDType a, vSIMDType b) noexcept                 { return bit_not (equal (a, b)); }\r
+    static forcedinline vSIMDType greaterThan (vSIMDType a, vSIMDType b) noexcept              { return (vSIMDType) vcgtq_f64 (a, b); }\r
+    static forcedinline vSIMDType greaterThanOrEqual (vSIMDType a, vSIMDType b) noexcept       { return (vSIMDType) vcgeq_f64 (a, b); }\r
+    static forcedinline bool      allEqual (vSIMDType a, vSIMDType b) noexcept                 { return (SIMDNativeOps<uint32_t>::sum ((SIMDNativeOps<uint32_t>::vSIMDType) notEqual (a, b)) == 0); }\r
+    static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return vmlaq_f64 (a, b, c); }\r
+    static forcedinline vSIMDType cmplxmul (vSIMDType a, vSIMDType b) noexcept                 { return fb::cmplxmul (a, b); }\r
+    static forcedinline double    sum (vSIMDType a) noexcept                                   { return fb::sum (a); }\r
+    static forcedinline vSIMDType oddevensum (vSIMDType a) noexcept                            { return a; }\r
+    static forcedinline vSIMDType truncate (vSIMDType a) noexcept                              { return vcvtq_f64_s64 (vcvtq_s64_f64 (a)); }\r
+};\r
+#else\r
 template <>\r
 struct SIMDNativeOps<double>\r
 {\r
@@ -468,8 +509,8 @@ struct SIMDNativeOps<double>
 \r
     static forcedinline vSIMDType expand (double s) noexcept                                   { return {{s, s}}; }\r
     static forcedinline vSIMDType load (const double* a) noexcept                              { return {{a[0], a[1]}}; }\r
-    static forcedinline void store (vSIMDType v, double* a) noexcept                           { a[0] = v.v[0]; a[1] = v.v[1]; }\r
-    static forcedinline double get (vSIMDType v, size_t i) noexcept                            { return v.v[i]; }\r
+    static forcedinline void      store (vSIMDType v, double* a) noexcept                      { a[0] = v.v[0]; a[1] = v.v[1]; }\r
+    static forcedinline double    get (vSIMDType v, size_t i) noexcept                         { return v.v[i]; }\r
     static forcedinline vSIMDType set (vSIMDType v, size_t i, double s) noexcept               { v.v[i] = s; return v; }\r
     static forcedinline vSIMDType add (vSIMDType a, vSIMDType b) noexcept                      { return {{a.v[0] + b.v[0], a.v[1] + b.v[1]}}; }\r
     static forcedinline vSIMDType sub (vSIMDType a, vSIMDType b) noexcept                      { return {{a.v[0] - b.v[0], a.v[1] - b.v[1]}}; }\r
@@ -488,12 +529,12 @@ struct SIMDNativeOps<double>
     static forcedinline bool      allEqual (vSIMDType a, vSIMDType b) noexcept                 { return fb::allEqual (a, b); }\r
     static forcedinline vSIMDType multiplyAdd (vSIMDType a, vSIMDType b, vSIMDType c) noexcept { return fb::multiplyAdd (a, b, c); }\r
     static forcedinline vSIMDType cmplxmul (vSIMDType a, vSIMDType b) noexcept                 { return fb::cmplxmul (a, b); }\r
-    static forcedinline double sum (vSIMDType a) noexcept                                      { return fb::sum (a); }\r
+    static forcedinline double    sum (vSIMDType a) noexcept                                   { return fb::sum (a); }\r
     static forcedinline vSIMDType oddevensum (vSIMDType a) noexcept                            { return a; }\r
     static forcedinline vSIMDType truncate (vSIMDType a) noexcept                              { return fb::truncate (a); }\r
 };\r
-\r
-#endif\r
+#endif // JUCE_64BIT\r
+#endif // #ifndef DOXYGEN\r
 \r
 JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
 \r
index a32295f001955d3d93bc802f492de09289e74440..0d92237606075b7b9de06b04e150f7c86f0c6673 100644 (file)
@@ -201,126 +201,104 @@ public:
 \r
 private:\r
     //==============================================================================\r
-    template <typename T = InterpolationType>\r
-    typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, SampleType>::type\r
-    interpolateSample (int channel) const\r
+    SampleType interpolateSample (int channel)\r
     {\r
-        auto index = (readPos[(size_t) channel] + delayInt) % totalSize;\r
-        return bufferData.getSample (channel, index);\r
-    }\r
-\r
-    template <typename T = InterpolationType>\r
-    typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, SampleType>::type\r
-    interpolateSample (int channel) const\r
-    {\r
-        auto index1 = readPos[(size_t) channel] + delayInt;\r
-        auto index2 = index1 + 1;\r
-\r
-        if (index2 >= totalSize)\r
+        if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::None>)\r
         {\r
-            index1 %= totalSize;\r
-            index2 %= totalSize;\r
+            auto index = (readPos[(size_t) channel] + delayInt) % totalSize;\r
+            return bufferData.getSample (channel, index);\r
         }\r
+        else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Linear>)\r
+        {\r
+            auto index1 = readPos[(size_t) channel] + delayInt;\r
+            auto index2 = index1 + 1;\r
 \r
-        auto value1 = bufferData.getSample (channel, index1);\r
-        auto value2 = bufferData.getSample (channel, index2);\r
-\r
-        return value1 + delayFrac * (value2 - value1);\r
-    }\r
+            if (index2 >= totalSize)\r
+            {\r
+                index1 %= totalSize;\r
+                index2 %= totalSize;\r
+            }\r
 \r
-    template <typename T = InterpolationType>\r
-    typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, SampleType>::type\r
-    interpolateSample (int channel) const\r
-    {\r
-        auto index1 = readPos[(size_t) channel] + delayInt;\r
-        auto index2 = index1 + 1;\r
-        auto index3 = index2 + 1;\r
-        auto index4 = index3 + 1;\r
+            auto value1 = bufferData.getSample (channel, index1);\r
+            auto value2 = bufferData.getSample (channel, index2);\r
 \r
-        if (index4 >= totalSize)\r
-        {\r
-            index1 %= totalSize;\r
-            index2 %= totalSize;\r
-            index3 %= totalSize;\r
-            index4 %= totalSize;\r
+            return value1 + delayFrac * (value2 - value1);\r
         }\r
+        else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)\r
+        {\r
+            auto index1 = readPos[(size_t) channel] + delayInt;\r
+            auto index2 = index1 + 1;\r
+            auto index3 = index2 + 1;\r
+            auto index4 = index3 + 1;\r
 \r
-        auto* samples = bufferData.getReadPointer (channel);\r
+            if (index4 >= totalSize)\r
+            {\r
+                index1 %= totalSize;\r
+                index2 %= totalSize;\r
+                index3 %= totalSize;\r
+                index4 %= totalSize;\r
+            }\r
 \r
-        auto value1 = samples[index1];\r
-        auto value2 = samples[index2];\r
-        auto value3 = samples[index3];\r
-        auto value4 = samples[index4];\r
+            auto* samples = bufferData.getReadPointer (channel);\r
 \r
-        auto d1 = delayFrac - 1.f;\r
-        auto d2 = delayFrac - 2.f;\r
-        auto d3 = delayFrac - 3.f;\r
+            auto value1 = samples[index1];\r
+            auto value2 = samples[index2];\r
+            auto value3 = samples[index3];\r
+            auto value4 = samples[index4];\r
 \r
-        auto c1 = -d1 * d2 * d3 / 6.f;\r
-        auto c2 = d2 * d3 * 0.5f;\r
-        auto c3 = -d1 * d3 * 0.5f;\r
-        auto c4 = d1 * d2 / 6.f;\r
+            auto d1 = delayFrac - 1.f;\r
+            auto d2 = delayFrac - 2.f;\r
+            auto d3 = delayFrac - 3.f;\r
 \r
-        return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);\r
-    }\r
+            auto c1 = -d1 * d2 * d3 / 6.f;\r
+            auto c2 = d2 * d3 * 0.5f;\r
+            auto c3 = -d1 * d3 * 0.5f;\r
+            auto c4 = d1 * d2 / 6.f;\r
 \r
-    template <typename T = InterpolationType>\r
-    typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, SampleType>::type\r
-    interpolateSample (int channel)\r
-    {\r
-        auto index1 = readPos[(size_t) channel] + delayInt;\r
-        auto index2 = index1 + 1;\r
-\r
-        if (index2 >= totalSize)\r
-        {\r
-            index1 %= totalSize;\r
-            index2 %= totalSize;\r
+            return value1 * c1 + delayFrac * (value2 * c2 + value3 * c3 + value4 * c4);\r
         }\r
+        else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)\r
+        {\r
+            auto index1 = readPos[(size_t) channel] + delayInt;\r
+            auto index2 = index1 + 1;\r
 \r
-        auto value1 = bufferData.getSample (channel, index1);\r
-        auto value2 = bufferData.getSample (channel, index2);\r
-\r
-        auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);\r
-        v[(size_t) channel] = output;\r
-\r
-        return output;\r
-    }\r
+            if (index2 >= totalSize)\r
+            {\r
+                index1 %= totalSize;\r
+                index2 %= totalSize;\r
+            }\r
 \r
-    //==============================================================================\r
-    template <typename T = InterpolationType>\r
-    typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::None>::value, void>::type\r
-    updateInternalVariables()\r
-    {\r
-    }\r
+            auto value1 = bufferData.getSample (channel, index1);\r
+            auto value2 = bufferData.getSample (channel, index2);\r
 \r
-    template <typename T = InterpolationType>\r
-    typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Linear>::value, void>::type\r
-    updateInternalVariables()\r
-    {\r
-    }\r
+            auto output = delayFrac == 0 ? value1 : value2 + alpha * (value1 - v[(size_t) channel]);\r
+            v[(size_t) channel] = output;\r
 \r
-    template <typename T = InterpolationType>\r
-    typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Lagrange3rd>::value, void>::type\r
-    updateInternalVariables()\r
-    {\r
-        if (delayInt >= 1)\r
-        {\r
-            delayFrac++;\r
-            delayInt--;\r
+            return output;\r
         }\r
     }\r
 \r
-    template <typename T = InterpolationType>\r
-    typename std::enable_if <std::is_same <T, DelayLineInterpolationTypes::Thiran>::value, void>::type\r
-    updateInternalVariables()\r
+    //==============================================================================\r
+    void updateInternalVariables()\r
     {\r
-        if (delayFrac < (SampleType) 0.618 && delayInt >= 1)\r
+        if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Lagrange3rd>)\r
         {\r
-            delayFrac++;\r
-            delayInt--;\r
+            if (delayInt >= 1)\r
+            {\r
+                delayFrac++;\r
+                delayInt--;\r
+            }\r
         }\r
+        else if constexpr (std::is_same_v<InterpolationType, DelayLineInterpolationTypes::Thiran>)\r
+        {\r
+            if (delayFrac < (SampleType) 0.618 && delayInt >= 1)\r
+            {\r
+                delayFrac++;\r
+                delayInt--;\r
+            }\r
 \r
-        alpha = (1 - delayFrac) / (1 + delayFrac);\r
+            alpha = (1 - delayFrac) / (1 + delayFrac);\r
+        }\r
     }\r
 \r
     //==============================================================================\r
index 560fdc2c8be3cefdeb59fd73a454caac0cf36e3c..203c12836b3c41bcb1ed80030c624cb02dd6032f 100644 (file)
@@ -122,7 +122,7 @@ namespace FIR
         template <typename ProcessContext>\r
         void process (const ProcessContext& context) noexcept\r
         {\r
-            static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,\r
+            static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,\r
                            "The sample-type of the FIR filter must match the sample-type supplied to this process callback");\r
             check();\r
 \r
index 9644f4dc9736457e907f0e5058039dbebe5c16c6..150ab429e946a6e202224ecc33618a94719185eb 100644 (file)
@@ -89,7 +89,7 @@ template <typename SampleType>
 template <typename ProcessContext, bool bypassed>\r
 void Filter<SampleType>::processInternal (const ProcessContext& context) noexcept\r
 {\r
-    static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,\r
+    static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,\r
                    "The sample-type of the IIR filter must match the sample-type supplied to this process callback");\r
     check();\r
 \r
index 3b0cdfe4fc1dcedb9999ac5ef609e3106e4e5ed4..9f821018c221c9fa65eb63e5a1e0fea14b1fdd4b 100644 (file)
@@ -38,11 +38,11 @@ namespace detail
     template <typename Fn, typename Tuple, size_t... Ix>\r
     constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple, std::index_sequence<Ix...>)\r
     {\r
-        (void) std::initializer_list<int> { ((void) fn (std::get<Ix> (tuple), std::integral_constant<size_t, Ix>()), 0)... };\r
+        (fn (std::get<Ix> (tuple), std::integral_constant<size_t, Ix>()), ...);\r
     }\r
 \r
     template <typename T>\r
-    using TupleIndexSequence = std::make_index_sequence<std::tuple_size<std::remove_cv_t<std::remove_reference_t<T>>>::value>;\r
+    using TupleIndexSequence = std::make_index_sequence<std::tuple_size_v<std::remove_cv_t<std::remove_reference_t<T>>>>;\r
 \r
     template <typename Fn, typename Tuple>\r
     constexpr void forEachInTuple (Fn&& fn, Tuple&& tuple)\r
@@ -50,12 +50,8 @@ namespace detail
         forEachInTuple (std::forward<Fn> (fn), std::forward<Tuple> (tuple), TupleIndexSequence<Tuple>{});\r
     }\r
 \r
-    // This could be a template variable, but that code causes an internal compiler error in MSVC 19.00.24215\r
     template <typename Context, size_t Ix>\r
-    struct UseContextDirectly\r
-    {\r
-        static constexpr auto value = ! Context::usesSeparateInputAndOutputBlocks() || Ix == 0;\r
-    };\r
+    inline constexpr auto useContextDirectly = ! Context::usesSeparateInputAndOutputBlocks() || Ix == 0;\r
 }\r
 #endif\r
 \r
@@ -103,23 +99,24 @@ public:
     }\r
 \r
 private:\r
-    template <typename Context, typename Proc, size_t Ix, std::enable_if_t<! detail::UseContextDirectly<Context, Ix>::value, int> = 0>\r
+    template <typename Context, typename Proc, size_t Ix>\r
     void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept\r
     {\r
-        jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels());\r
-        ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock());\r
-        replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed);\r
-\r
-        proc.process (replacingContext);\r
-    }\r
-\r
-    template <typename Context, typename Proc, size_t Ix, std::enable_if_t<detail::UseContextDirectly<Context, Ix>::value, int> = 0>\r
-    void processOne (const Context& context, Proc& proc, std::integral_constant<size_t, Ix>) noexcept\r
-    {\r
-        auto contextCopy = context;\r
-        contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed);\r
-\r
-        proc.process (contextCopy);\r
+        if constexpr (detail::useContextDirectly<Context, Ix>)\r
+        {\r
+            auto contextCopy = context;\r
+            contextCopy.isBypassed = (bypassed[Ix] || context.isBypassed);\r
+\r
+            proc.process (contextCopy);\r
+        }\r
+        else\r
+        {\r
+            jassert (context.getOutputBlock().getNumChannels() == context.getInputBlock().getNumChannels());\r
+            ProcessContextReplacing<typename Context::SampleType> replacingContext (context.getOutputBlock());\r
+            replacingContext.isBypassed = (bypassed[Ix] || context.isBypassed);\r
+\r
+            proc.process (replacingContext);\r
+        }\r
     }\r
 \r
     std::tuple<Processors...> processors;\r
index 9a991608429a4cefbcc267c5766d616cd80380d2..6554b2bc6e39cc785affd3584bacfa4e92512103 100644 (file)
@@ -110,7 +110,7 @@ namespace StateVariableFilter
         template <typename ProcessContext>\r
         void process (const ProcessContext& context) noexcept\r
         {\r
-            static_assert (std::is_same<typename ProcessContext::SampleType, SampleType>::value,\r
+            static_assert (std::is_same_v<typename ProcessContext::SampleType, SampleType>,\r
                            "The sample-type of the filter must match the sample-type supplied to this process callback");\r
 \r
             if (context.isBypassed)\r
index 30dfdb3b359765ec72a914e55236a4f07026ea82..995c20e7d7f0f875d7c9ca1a35d8ea7682abfdbc 100644 (file)
@@ -71,7 +71,7 @@ struct WaveShaper
 };\r
 \r
 //==============================================================================\r
-#if JUCE_CXX17_IS_AVAILABLE && ! ((JUCE_MAC || JUCE_IOS) && JUCE_CLANG && __clang_major__ < 10)\r
+#if ! ((JUCE_MAC || JUCE_IOS) && JUCE_CLANG && __clang_major__ < 10)\r
 template <typename Functor>\r
 static WaveShaper<typename std::invoke_result<Functor>, Functor> CreateWaveShaper (Functor functionToUse)   { return {functionToUse}; }\r
 #else\r
index d7e4b00ad56927faf4e4c81da79b9ff8741ce79a..dce744f39208408e1e01768017f7ed0f47c9e056 100644 (file)
@@ -51,7 +51,7 @@ struct ChildProcessPingThread  : public Thread,
         pingReceived();\r
     }\r
 \r
-    void startPinging()                     { startThread (4); }\r
+    void startPinging()                     { startThread (Priority::low); }\r
 \r
     void pingReceived() noexcept            { countdown = timeoutMs / 1000 + 1; }\r
     void triggerConnectionLostMessage()     { triggerAsyncUpdate(); }\r
index f1b006d6a09ba59d834449687289966ddf1e12be..add5e52170f293cb8afa2fc226e81dc92e129c2f 100644 (file)
@@ -41,7 +41,7 @@ NetworkServiceDiscovery::Advertiser::Advertiser (const String& serviceTypeUID,
     message.setAttribute ("address", String());\r
     message.setAttribute ("port", connectionPort);\r
 \r
-    startThread (2);\r
+    startThread (Priority::background);\r
 }\r
 \r
 NetworkServiceDiscovery::Advertiser::~Advertiser()\r
@@ -92,7 +92,7 @@ NetworkServiceDiscovery::AvailableServiceList::AvailableServiceList (const Strin
    #endif\r
 \r
     socket.bindToPort (broadcastPort);\r
-    startThread (2);\r
+    startThread (Priority::background);\r
 }\r
 \r
 NetworkServiceDiscovery::AvailableServiceList::~AvailableServiceList()\r
index 6f7e50604e7defaff9727674081c566d30d40c64..b3d60e3848ce0f995e17f81349868e77f8d4bd4f 100644 (file)
 \r
   ID:                 juce_events\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE message and event handling classes\r
   description:        Classes for running an application's main event loop and sending/receiving messages, timers, etc.\r
   website:            http://www.juce.com/juce\r
   license:            ISC\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_core\r
 \r
index 604a649e6554c93d342c4588f97a100987c9ee98..04f534bef6e205a5e58841401eb8c502d88a8afc 100644 (file)
@@ -199,14 +199,12 @@ String JUCEApplicationBase::getCommandLineParameters()
 {\r
     String argString;\r
 \r
-    for (int i = 1; i < juce_argc; ++i)\r
+    for (const auto& arg : getCommandLineParameterArray())\r
     {\r
-        String arg { CharPointer_UTF8 (juce_argv[i]) };\r
-\r
-        if (arg.containsChar (' ') && ! arg.isQuotedString())\r
-            arg = arg.quoted ('"');\r
-\r
-        argString << arg << ' ';\r
+        const auto withQuotes = arg.containsChar (' ') && ! arg.isQuotedString()\r
+                              ? arg.quoted ('"')\r
+                              : arg;\r
+        argString << withQuotes << ' ';\r
     }\r
 \r
     return argString.trim();\r
@@ -214,7 +212,12 @@ String JUCEApplicationBase::getCommandLineParameters()
 \r
 StringArray JUCEApplicationBase::getCommandLineParameterArray()\r
 {\r
-    return StringArray (juce_argv + 1, juce_argc - 1);\r
+    StringArray result;\r
+\r
+    for (int i = 1; i < juce_argc; ++i)\r
+        result.add (CharPointer_UTF8 (juce_argv[i]));\r
+\r
+    return result;\r
 }\r
 \r
 int JUCEApplicationBase::main (int argc, const char* argv[])\r
index dcf583346693e5cbea53e21bdadbf0fb87b230f1..69fa23943fa36dd2a969f72076931427b49df795 100644 (file)
@@ -68,8 +68,7 @@ public:
 \r
             ScopedUnlock ul (lock);\r
             unsigned char x = 0xff;\r
-            auto numBytes = write (getWriteHandle(), &x, 1);\r
-            ignoreUnused (numBytes);\r
+            [[maybe_unused]] auto numBytes = write (getWriteHandle(), &x, 1);\r
         }\r
     }\r
 \r
@@ -97,8 +96,7 @@ private:
 \r
             ScopedUnlock ul (lock);\r
             unsigned char x;\r
-            auto numBytes = read (fd, &x, 1);\r
-            ignoreUnused (numBytes);\r
+            [[maybe_unused]] auto numBytes = read (fd, &x, 1);\r
         }\r
 \r
         return queue.removeAndReturn (0);\r
index 3266f7a3eba987d43cc4d17c215839ce42fcad74..0e91c21596286d36db244811d2a48029fdbf7f36 100644 (file)
@@ -288,7 +288,7 @@ void MessageManager::broadcastMessage (const String& value)
 //==============================================================================\r
 void MessageManager::doPlatformSpecificInitialisation()\r
 {\r
-    ignoreUnused (OleInitialize (nullptr));\r
+    [[maybe_unused]] const auto result = OleInitialize (nullptr);\r
     InternalMessageQueue::getInstance();\r
 }\r
 \r
index af4a79372db7fd3e35517378d9c87e52187dd4ae..fca7cc3021f4dc18729d47ce78f1d3b5c0243f47 100644 (file)
@@ -42,7 +42,7 @@ WinRTWrapper::WinRTWrapper()
         return;\r
 \r
     HRESULT status = roInitialize (1);\r
-    initialised = ! (status != S_OK && status != S_FALSE && status != 0x80010106L);\r
+    initialised = ! (status != S_OK && status != S_FALSE && status != (HRESULT) 0x80010106L);\r
 }\r
 \r
 WinRTWrapper::~WinRTWrapper()\r
index af0e1b96fd235a52545ab3ff9e471d8234e8c0e4..12c67f2f8500714f16badd53b341f049e8dec3ea 100644 (file)
@@ -30,7 +30,7 @@ public:
     ~WinRTWrapper();\r
     bool isInitialised() const noexcept  { return initialised; }\r
 \r
-    JUCE_DECLARE_SINGLETON (WinRTWrapper, true)\r
+    JUCE_DECLARE_SINGLETON (WinRTWrapper, false)\r
 \r
     //==============================================================================\r
     template <class ComClass>\r
index 3da0766dee2ee0cded92d537c261725e7fd9e008..2dde51bc116370ae13e3df5260f3b30775ea2266 100644 (file)
@@ -303,7 +303,7 @@ private:
 \r
     void handleAsyncUpdate() override\r
     {\r
-        startThread (7);\r
+        startThread (Priority::high);\r
     }\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TimerThread)\r
index b8e10580d965880c0035378a6b010082bb973a4f..3077addde61e9fe88941145383d1edabd7d4f53b 100644 (file)
@@ -299,35 +299,35 @@ public:
 \r
     //==============================================================================\r
     /** Returns a copy of this colour with a different hue. */\r
-    JUCE_NODISCARD Colour withHue (float newHue) const noexcept;\r
+    [[nodiscard]] Colour withHue (float newHue) const noexcept;\r
 \r
     /** Returns a copy of this colour with a different saturation. */\r
-    JUCE_NODISCARD Colour withSaturation (float newSaturation) const noexcept;\r
+    [[nodiscard]] Colour withSaturation (float newSaturation) const noexcept;\r
 \r
     /** Returns a copy of this colour with a different saturation in the HSL colour space. */\r
-    JUCE_NODISCARD Colour withSaturationHSL (float newSaturation) const noexcept;\r
+    [[nodiscard]] Colour withSaturationHSL (float newSaturation) const noexcept;\r
 \r
     /** Returns a copy of this colour with a different brightness.\r
         @see brighter, darker, withMultipliedBrightness\r
     */\r
-    JUCE_NODISCARD Colour withBrightness (float newBrightness) const noexcept;\r
+    [[nodiscard]] Colour withBrightness (float newBrightness) const noexcept;\r
 \r
     /** Returns a copy of this colour with a different lightness.\r
         @see lighter, darker, withMultipliedLightness\r
     */\r
-    JUCE_NODISCARD Colour withLightness (float newLightness) const noexcept;\r
+    [[nodiscard]] Colour withLightness (float newLightness) const noexcept;\r
 \r
     /** Returns a copy of this colour with its hue rotated.\r
         The new colour's hue is ((this->getHue() + amountToRotate) % 1.0)\r
         @see brighter, darker, withMultipliedBrightness\r
     */\r
-    JUCE_NODISCARD Colour withRotatedHue (float amountToRotate) const noexcept;\r
+    [[nodiscard]] Colour withRotatedHue (float amountToRotate) const noexcept;\r
 \r
     /** Returns a copy of this colour with its saturation multiplied by the given value.\r
         The new colour's saturation is (this->getSaturation() * multiplier)\r
         (the result is clipped to legal limits).\r
     */\r
-    JUCE_NODISCARD Colour withMultipliedSaturation (float multiplier) const noexcept;\r
+    [[nodiscard]] Colour withMultipliedSaturation (float multiplier) const noexcept;\r
 \r
     /** Returns a copy of this colour with its saturation multiplied by the given value.\r
         The new colour's saturation is (this->getSaturation() * multiplier)\r
@@ -335,19 +335,19 @@ public:
 \r
         This will be in the HSL colour space.\r
     */\r
-    JUCE_NODISCARD Colour withMultipliedSaturationHSL (float multiplier) const noexcept;\r
+    [[nodiscard]] Colour withMultipliedSaturationHSL (float multiplier) const noexcept;\r
 \r
     /** Returns a copy of this colour with its brightness multiplied by the given value.\r
         The new colour's brightness is (this->getBrightness() * multiplier)\r
         (the result is clipped to legal limits).\r
     */\r
-    JUCE_NODISCARD Colour withMultipliedBrightness (float amount) const noexcept;\r
+    [[nodiscard]] Colour withMultipliedBrightness (float amount) const noexcept;\r
 \r
     /** Returns a copy of this colour with its lightness multiplied by the given value.\r
         The new colour's lightness is (this->lightness() * multiplier)\r
         (the result is clipped to legal limits).\r
     */\r
-    JUCE_NODISCARD Colour withMultipliedLightness (float amount) const noexcept;\r
+    [[nodiscard]] Colour withMultipliedLightness (float amount) const noexcept;\r
 \r
     //==============================================================================\r
     /** Returns a brighter version of this colour.\r
@@ -355,14 +355,14 @@ public:
                                 where 0 is unchanged, and higher values make it brighter\r
         @see withMultipliedBrightness\r
     */\r
-    JUCE_NODISCARD Colour brighter (float amountBrighter = 0.4f) const noexcept;\r
+    [[nodiscard]] Colour brighter (float amountBrighter = 0.4f) const noexcept;\r
 \r
     /** Returns a darker version of this colour.\r
         @param amountDarker     how much darker to make it - a value greater than or equal to 0,\r
                                 where 0 is unchanged, and higher values make it darker\r
         @see withMultipliedBrightness\r
     */\r
-    JUCE_NODISCARD Colour darker (float amountDarker = 0.4f) const noexcept;\r
+    [[nodiscard]] Colour darker (float amountDarker = 0.4f) const noexcept;\r
 \r
     //==============================================================================\r
     /** Returns a colour that will be clearly visible against this colour.\r
@@ -372,7 +372,7 @@ public:
         that's just a little bit lighter; Colours::black.contrasting (1.0f) will\r
         return white; Colours::white.contrasting (1.0f) will return black, etc.\r
     */\r
-    JUCE_NODISCARD Colour contrasting (float amount = 1.0f) const noexcept;\r
+    [[nodiscard]] Colour contrasting (float amount = 1.0f) const noexcept;\r
 \r
     /** Returns a colour that is as close as possible to a target colour whilst\r
         still being in contrast to this one.\r
@@ -381,20 +381,20 @@ public:
         nudged up or down so that it differs from the luminosity of this colour\r
         by at least the amount specified by minLuminosityDiff.\r
     */\r
-    JUCE_NODISCARD Colour contrasting (Colour targetColour, float minLuminosityDiff) const noexcept;\r
+    [[nodiscard]] Colour contrasting (Colour targetColour, float minLuminosityDiff) const noexcept;\r
 \r
     /** Returns a colour that contrasts against two colours.\r
         Looks for a colour that contrasts with both of the colours passed-in.\r
         Handy for things like choosing a highlight colour in text editors, etc.\r
     */\r
-    JUCE_NODISCARD static Colour contrasting (Colour colour1,\r
+    [[nodiscard]] static Colour contrasting (Colour colour1,\r
                                               Colour colour2) noexcept;\r
 \r
     //==============================================================================\r
     /** Returns an opaque shade of grey.\r
         @param brightness the level of grey to return - 0 is black, 1.0 is white\r
     */\r
-    JUCE_NODISCARD static Colour greyLevel (float brightness) noexcept;\r
+    [[nodiscard]] static Colour greyLevel (float brightness) noexcept;\r
 \r
     //==============================================================================\r
     /** Returns a stringified version of this colour.\r
@@ -403,7 +403,7 @@ public:
     String toString() const;\r
 \r
     /** Reads the colour from a string that was created with toString(). */\r
-    JUCE_NODISCARD static Colour fromString (StringRef encodedColourString);\r
+    [[nodiscard]] static Colour fromString (StringRef encodedColourString);\r
 \r
     /** Returns the colour as a hex string in the form RRGGBB or AARRGGBB. */\r
     String toDisplayString (bool includeAlphaValue) const;\r
index 4cf700771b37d158084a23344493c41ef6bbaeee..640ac3b599b02118413a8758f3d1293fa2f8898a 100644 (file)
@@ -540,18 +540,16 @@ void Graphics::fillRectList (const RectangleList<int>& rects) const
 \r
 void Graphics::fillAll() const\r
 {\r
-    fillRect (context.getClipBounds());\r
+    context.fillAll();\r
 }\r
 \r
 void Graphics::fillAll (Colour colourToUse) const\r
 {\r
     if (! colourToUse.isTransparent())\r
     {\r
-        auto clip = context.getClipBounds();\r
-\r
         context.saveState();\r
         context.setFill (colourToUse);\r
-        context.fillRect (clip, false);\r
+        context.fillAll();\r
         context.restoreState();\r
     }\r
 }\r
index e34a42fe6c6f788faa531e69ccf09a76313155b6..29070743b3be3bedd7eb7cb78afd5835ab0a4395 100644 (file)
@@ -86,6 +86,7 @@ public:
     virtual void setInterpolationQuality (Graphics::ResamplingQuality) = 0;\r
 \r
     //==============================================================================\r
+    virtual void fillAll() { fillRect (getClipBounds(), false); }\r
     virtual void fillRect (const Rectangle<int>&, bool replaceExistingContents) = 0;\r
     virtual void fillRect (const Rectangle<float>&) = 0;\r
     virtual void fillRectList (const RectangleList<float>&) = 0;\r
index 8b4e9601096574027d5be01a5aeae332032d0742..dbcf8d1845c5915595f5c9a08f7e3c3d1ede176e 100644 (file)
@@ -154,7 +154,7 @@ public:
     /** Returns a copy of this font with a new typeface style.\r
         @see getAvailableStyles()\r
     */\r
-    JUCE_NODISCARD Font withTypefaceStyle (const String& newStyle) const;\r
+    [[nodiscard]] Font withTypefaceStyle (const String& newStyle) const;\r
 \r
     /** Returns a list of the styles that this font can use. */\r
     StringArray getAvailableStyles() const;\r
@@ -204,10 +204,10 @@ public:
 \r
     //==============================================================================\r
     /** Returns a copy of this font with a new height. */\r
-    JUCE_NODISCARD Font withHeight (float height) const;\r
+    [[nodiscard]] Font withHeight (float height) const;\r
 \r
     /** Returns a copy of this font with a new height, specified in points. */\r
-    JUCE_NODISCARD Font withPointHeight (float heightInPoints) const;\r
+    [[nodiscard]] Font withPointHeight (float heightInPoints) const;\r
 \r
     /** Changes the font's height.\r
         @see getHeight, withHeight, setHeightWithoutChangingWidth\r
@@ -271,7 +271,7 @@ public:
         @param styleFlags     a bitwise-or'ed combination of values from the FontStyleFlags enum.\r
         @see FontStyleFlags, getStyleFlags\r
     */\r
-    JUCE_NODISCARD Font withStyle (int styleFlags) const;\r
+    [[nodiscard]] Font withStyle (int styleFlags) const;\r
 \r
     /** Changes the font's style.\r
         @param newFlags     a bitwise-or'ed combination of values from the FontStyleFlags enum.\r
@@ -286,7 +286,7 @@ public:
     /** Returns a copy of this font with the bold attribute set.\r
         If the font does not have a bold version, this will return the default font.\r
      */\r
-    JUCE_NODISCARD Font boldened() const;\r
+    [[nodiscard]] Font boldened() const;\r
 \r
     /** Returns true if the font is bold. */\r
     bool isBold() const noexcept;\r
@@ -294,7 +294,7 @@ public:
     /** Makes the font italic or non-italic. */\r
     void setItalic (bool shouldBeItalic);\r
     /** Returns a copy of this font with the italic attribute set. */\r
-    JUCE_NODISCARD Font italicised() const;\r
+    [[nodiscard]] Font italicised() const;\r
     /** Returns true if the font is italic. */\r
     bool isItalic() const noexcept;\r
 \r
@@ -317,7 +317,7 @@ public:
                             narrower, greater than 1.0 will be stretched out.\r
         @see getHorizontalScale\r
     */\r
-    JUCE_NODISCARD Font withHorizontalScale (float scaleFactor) const;\r
+    [[nodiscard]] Font withHorizontalScale (float scaleFactor) const;\r
 \r
     /** Changes the font's horizontal scale factor.\r
         @param scaleFactor  a value of 1.0 is the normal scale, less than this will be\r
@@ -353,7 +353,7 @@ public:
                                 normal spacing, positive values spread the letters out,\r
                                 negative values make them closer together.\r
     */\r
-    JUCE_NODISCARD Font withExtraKerningFactor (float extraKerning) const;\r
+    [[nodiscard]] Font withExtraKerningFactor (float extraKerning) const;\r
 \r
     /** Changes the font's kerning.\r
         @param extraKerning     a multiple of the font's height that will be added\r
index 7e7e98235be04d634a901d848c7efe09a8f45f35..7bd2a0b861e465ff7ee93dbb5bd3f05a698ceabc 100644 (file)
@@ -44,7 +44,7 @@ private:
     class DereferencingIterator\r
     {\r
     public:\r
-        using value_type = typename std::remove_reference<decltype(**std::declval<Iterator>())>::type;\r
+        using value_type = std::remove_reference_t<decltype(**std::declval<Iterator>())>;\r
         using difference_type = typename std::iterator_traits<Iterator>::difference_type;\r
         using pointer = value_type*;\r
         using reference = value_type&;\r
index da183d1e11805e4b116eb2d53f965896d34af926..5525328855c19706b0707ce52044e76550e44934 100644 (file)
@@ -123,7 +123,7 @@ public:
     template <typename OtherType>\r
     constexpr Point operator* (OtherType multiplier) const noexcept\r
     {\r
-        using CommonType = typename std::common_type<ValueType, OtherType>::type;\r
+        using CommonType = std::common_type_t<ValueType, OtherType>;\r
         return Point ((ValueType) ((CommonType) x * (CommonType) multiplier),\r
                       (ValueType) ((CommonType) y * (CommonType) multiplier));\r
     }\r
@@ -132,7 +132,7 @@ public:
     template <typename OtherType>\r
     constexpr Point operator/ (OtherType divisor) const noexcept\r
     {\r
-        using CommonType = typename std::common_type<ValueType, OtherType>::type;\r
+        using CommonType = std::common_type_t<ValueType, OtherType>;\r
         return Point ((ValueType) ((CommonType) x / (CommonType) divisor),\r
                       (ValueType) ((CommonType) y / (CommonType) divisor));\r
     }\r
@@ -150,7 +150,7 @@ public:
 \r
     //==============================================================================\r
     /** This type will be double if the Point's type is double, otherwise it will be float. */\r
-    using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type;\r
+    using FloatType = TypeHelpers::SmallestFloatType<ValueType>;\r
 \r
     //==============================================================================\r
     /** Returns the straight-line distance between this point and the origin. */\r
index db7b479d0fe52946976cdad2c315ae38fe0470fb..9789f7ee275d2a6fb6d940062ed9b6d41ce8e813 100644 (file)
@@ -217,41 +217,41 @@ public:
     void setVerticalRange (Range<ValueType> range) noexcept                                         { pos.y = range.getStart(); h = range.getLength(); }\r
 \r
     /** Returns a rectangle which has the same size and y-position as this one, but with a different x-position. */\r
-    JUCE_NODISCARD Rectangle withX (ValueType newX) const noexcept                                  { return { newX, pos.y, w, h }; }\r
+    [[nodiscard]] Rectangle withX (ValueType newX) const noexcept                                  { return { newX, pos.y, w, h }; }\r
 \r
     /** Returns a rectangle which has the same size and x-position as this one, but with a different y-position. */\r
-    JUCE_NODISCARD Rectangle withY (ValueType newY) const noexcept                                  { return { pos.x, newY, w, h }; }\r
+    [[nodiscard]] Rectangle withY (ValueType newY) const noexcept                                  { return { pos.x, newY, w, h }; }\r
 \r
     /** Returns a rectangle which has the same size and y-position as this one, but whose right-hand edge has the given position. */\r
-    JUCE_NODISCARD Rectangle withRightX (ValueType newRightX) const noexcept                        { return { newRightX - w, pos.y, w, h }; }\r
+    [[nodiscard]] Rectangle withRightX (ValueType newRightX) const noexcept                        { return { newRightX - w, pos.y, w, h }; }\r
 \r
     /** Returns a rectangle which has the same size and x-position as this one, but whose bottom edge has the given position. */\r
-    JUCE_NODISCARD Rectangle withBottomY (ValueType newBottomY) const noexcept                      { return { pos.x, newBottomY - h, w, h }; }\r
+    [[nodiscard]] Rectangle withBottomY (ValueType newBottomY) const noexcept                      { return { pos.x, newBottomY - h, w, h }; }\r
 \r
     /** Returns a rectangle with the same size as this one, but a new position. */\r
-    JUCE_NODISCARD Rectangle withPosition (ValueType newX, ValueType newY) const noexcept           { return { newX, newY, w, h }; }\r
+    [[nodiscard]] Rectangle withPosition (ValueType newX, ValueType newY) const noexcept           { return { newX, newY, w, h }; }\r
 \r
     /** Returns a rectangle with the same size as this one, but a new position. */\r
-    JUCE_NODISCARD Rectangle withPosition (Point<ValueType> newPos) const noexcept                  { return { newPos.x, newPos.y, w, h }; }\r
+    [[nodiscard]] Rectangle withPosition (Point<ValueType> newPos) const noexcept                  { return { newPos.x, newPos.y, w, h }; }\r
 \r
     /** Returns a rectangle whose size is the same as this one, but whose top-left position is (0, 0). */\r
-    JUCE_NODISCARD Rectangle withZeroOrigin() const noexcept                                        { return { w, h }; }\r
+    [[nodiscard]] Rectangle withZeroOrigin() const noexcept                                        { return { w, h }; }\r
 \r
     /** Returns a rectangle with the same size as this one, but a new centre position. */\r
-    JUCE_NODISCARD Rectangle withCentre (Point<ValueType> newCentre) const noexcept                 { return { newCentre.x - w / (ValueType) 2,\r
+    [[nodiscard]] Rectangle withCentre (Point<ValueType> newCentre) const noexcept                 { return { newCentre.x - w / (ValueType) 2,\r
                                                                                                                newCentre.y - h / (ValueType) 2, w, h }; }\r
 \r
     /** Returns a rectangle which has the same position and height as this one, but with a different width. */\r
-    JUCE_NODISCARD Rectangle withWidth (ValueType newWidth) const noexcept                          { return { pos.x, pos.y, jmax (ValueType(), newWidth), h }; }\r
+    [[nodiscard]] Rectangle withWidth (ValueType newWidth) const noexcept                          { return { pos.x, pos.y, jmax (ValueType(), newWidth), h }; }\r
 \r
     /** Returns a rectangle which has the same position and width as this one, but with a different height. */\r
-    JUCE_NODISCARD Rectangle withHeight (ValueType newHeight) const noexcept                        { return { pos.x, pos.y, w, jmax (ValueType(), newHeight) }; }\r
+    [[nodiscard]] Rectangle withHeight (ValueType newHeight) const noexcept                        { return { pos.x, pos.y, w, jmax (ValueType(), newHeight) }; }\r
 \r
     /** Returns a rectangle with the same top-left position as this one, but a new size. */\r
-    JUCE_NODISCARD Rectangle withSize (ValueType newWidth, ValueType newHeight) const noexcept      { return { pos.x, pos.y, jmax (ValueType(), newWidth), jmax (ValueType(), newHeight) }; }\r
+    [[nodiscard]] Rectangle withSize (ValueType newWidth, ValueType newHeight) const noexcept      { return { pos.x, pos.y, jmax (ValueType(), newWidth), jmax (ValueType(), newHeight) }; }\r
 \r
     /** Returns a rectangle with the same centre position as this one, but a new size. */\r
-    JUCE_NODISCARD Rectangle withSizeKeepingCentre (ValueType newWidth, ValueType newHeight) const noexcept { return { pos.x + (w - newWidth)  / (ValueType) 2,\r
+    [[nodiscard]] Rectangle withSizeKeepingCentre (ValueType newWidth, ValueType newHeight) const noexcept { return { pos.x + (w - newWidth)  / (ValueType) 2,\r
                                                                                                                        pos.y + (h - newHeight) / (ValueType) 2, newWidth, newHeight }; }\r
 \r
     /** Moves the x position, adjusting the width so that the right-hand edge remains in the same place.\r
@@ -264,7 +264,7 @@ public:
         If the new x is beyond the right of the current right-hand edge, the width will be set to zero.\r
         @see setLeft\r
     */\r
-    JUCE_NODISCARD Rectangle withLeft (ValueType newLeft) const noexcept       { return { newLeft, pos.y, jmax (ValueType(), pos.x + w - newLeft), h }; }\r
+    [[nodiscard]] Rectangle withLeft (ValueType newLeft) const noexcept       { return { newLeft, pos.y, jmax (ValueType(), pos.x + w - newLeft), h }; }\r
 \r
     /** Moves the y position, adjusting the height so that the bottom edge remains in the same place.\r
         If the y is moved to be below the current bottom edge, the height will be set to zero.\r
@@ -276,7 +276,7 @@ public:
         If the new y is beyond the bottom of the current rectangle, the height will be set to zero.\r
         @see setTop\r
     */\r
-    JUCE_NODISCARD Rectangle withTop (ValueType newTop) const noexcept         { return { pos.x, newTop, w, jmax (ValueType(), pos.y + h - newTop) }; }\r
+    [[nodiscard]] Rectangle withTop (ValueType newTop) const noexcept         { return { pos.x, newTop, w, jmax (ValueType(), pos.y + h - newTop) }; }\r
 \r
     /** Adjusts the width so that the right-hand edge of the rectangle has this new value.\r
         If the new right is below the current X value, the X will be pushed down to match it.\r
@@ -288,7 +288,7 @@ public:
         If the new right edge is below the current left-hand edge, the width will be set to zero.\r
         @see setRight\r
     */\r
-    JUCE_NODISCARD Rectangle withRight (ValueType newRight) const noexcept     { return { jmin (pos.x, newRight), pos.y, jmax (ValueType(), newRight - pos.x), h }; }\r
+    [[nodiscard]] Rectangle withRight (ValueType newRight) const noexcept     { return { jmin (pos.x, newRight), pos.y, jmax (ValueType(), newRight - pos.x), h }; }\r
 \r
     /** Adjusts the height so that the bottom edge of the rectangle has this new value.\r
         If the new bottom is lower than the current Y value, the Y will be pushed down to match it.\r
@@ -300,19 +300,19 @@ public:
         If the new y is beyond the bottom of the current rectangle, the height will be set to zero.\r
         @see setBottom\r
     */\r
-    JUCE_NODISCARD Rectangle withBottom (ValueType newBottom) const noexcept   { return { pos.x, jmin (pos.y, newBottom), w, jmax (ValueType(), newBottom - pos.y) }; }\r
+    [[nodiscard]] Rectangle withBottom (ValueType newBottom) const noexcept   { return { pos.x, jmin (pos.y, newBottom), w, jmax (ValueType(), newBottom - pos.y) }; }\r
 \r
     /** Returns a version of this rectangle with the given amount removed from its left-hand edge. */\r
-    JUCE_NODISCARD Rectangle withTrimmedLeft (ValueType amountToRemove) const noexcept     { return withLeft (pos.x + amountToRemove); }\r
+    [[nodiscard]] Rectangle withTrimmedLeft (ValueType amountToRemove) const noexcept     { return withLeft (pos.x + amountToRemove); }\r
 \r
     /** Returns a version of this rectangle with the given amount removed from its right-hand edge. */\r
-    JUCE_NODISCARD Rectangle withTrimmedRight (ValueType amountToRemove) const noexcept    { return withWidth (w - amountToRemove); }\r
+    [[nodiscard]] Rectangle withTrimmedRight (ValueType amountToRemove) const noexcept    { return withWidth (w - amountToRemove); }\r
 \r
     /** Returns a version of this rectangle with the given amount removed from its top edge. */\r
-    JUCE_NODISCARD Rectangle withTrimmedTop (ValueType amountToRemove) const noexcept      { return withTop (pos.y + amountToRemove); }\r
+    [[nodiscard]] Rectangle withTrimmedTop (ValueType amountToRemove) const noexcept      { return withTop (pos.y + amountToRemove); }\r
 \r
     /** Returns a version of this rectangle with the given amount removed from its bottom edge. */\r
-    JUCE_NODISCARD Rectangle withTrimmedBottom (ValueType amountToRemove) const noexcept   { return withHeight (h - amountToRemove); }\r
+    [[nodiscard]] Rectangle withTrimmedBottom (ValueType amountToRemove) const noexcept   { return withHeight (h - amountToRemove); }\r
 \r
     //==============================================================================\r
     /** Moves the rectangle's position by adding amount to its x and y coordinates. */\r
@@ -813,7 +813,7 @@ public:
     */\r
     Rectangle transformedBy (const AffineTransform& transform) const noexcept\r
     {\r
-        using FloatType = typename TypeHelpers::SmallestFloatType<ValueType>::type;\r
+        using FloatType = TypeHelpers::SmallestFloatType<ValueType>;\r
 \r
         auto x1 = static_cast<FloatType> (pos.x),     y1 = static_cast<FloatType> (pos.y);\r
         auto x2 = static_cast<FloatType> (pos.x + w), y2 = static_cast<FloatType> (pos.y);\r
index 8e106cd40ec5f4c243017a12d305abfcd4249b01..c05a698433838fc7e668b26696f20494142232e3 100644 (file)
@@ -201,76 +201,108 @@ public:
         Any rectangles in the list which overlap this will be clipped and subdivided\r
         if necessary.\r
     */\r
-    void subtract (RectangleType rect)\r
+    void subtract (const RectangleType rect)\r
     {\r
         if (auto numRects = rects.size())\r
         {\r
-            auto x1 = rect.getX();\r
-            auto y1 = rect.getY();\r
-            auto x2 = x1 + rect.getWidth();\r
-            auto y2 = y1 + rect.getHeight();\r
+            const auto x1 = rect.getX();\r
+            const auto y1 = rect.getY();\r
+            const auto x2 = x1 + rect.getWidth();\r
+            const auto y2 = y1 + rect.getHeight();\r
 \r
             for (int i = numRects; --i >= 0;)\r
             {\r
                 auto& r = rects.getReference (i);\r
 \r
-                auto rx1 = r.getX();\r
-                auto ry1 = r.getY();\r
-                auto rx2 = rx1 + r.getWidth();\r
-                auto ry2 = ry1 + r.getHeight();\r
+                const auto rx1 = r.getX();\r
+                const auto ry1 = r.getY();\r
+                const auto rx2 = rx1 + r.getWidth();\r
+                const auto ry2 = ry1 + r.getHeight();\r
 \r
-                if (! (x2 <= rx1 || x1 >= rx2 || y2 <= ry1 || y1 >= ry2))\r
+                const auto isNotEqual = [&] (const RectangleType newRect)\r
                 {\r
-                    if (x1 > rx1 && x1 < rx2)\r
+                    // When subtracting tiny slices from relatively large rectangles, the\r
+                    // subtraction may have no effect (due to limited-precision floating point\r
+                    // maths) and the original rectangle may remain unchanged.\r
+                    // We check that any 'new' rectangle has different dimensions to the rectangle\r
+                    // being tested before adding it to the rects array.\r
+                    // Integer arithmetic is not susceptible to this problem, so there's no need\r
+                    // for this additional equality check when working with integral rectangles.\r
+                    if constexpr (std::is_floating_point_v<ValueType>)\r
                     {\r
-                        if (y1 <= ry1 && y2 >= ry2 && x2 >= rx2)\r
+                        return newRect != r;\r
+                    }\r
+                    else\r
+                    {\r
+                        ignoreUnused (newRect);\r
+                        return true;\r
+                    }\r
+                };\r
+\r
+                if (rx1 < x2 && x1 < rx2 && ry1 < y2 && y1 < ry2)\r
+                {\r
+                    if (rx1 < x1 && x1 < rx2)\r
+                    {\r
+                        if (y1 <= ry1 && ry2 <= y2 && rx2 <= x2)\r
                         {\r
                             r.setWidth (x1 - rx1);\r
                         }\r
                         else\r
                         {\r
-                            r.setX (x1);\r
-                            r.setWidth (rx2 - x1);\r
-\r
-                            rects.insert (++i, RectangleType (rx1, ry1, x1 - rx1,  ry2 - ry1));\r
-                            ++i;\r
+                            if (const RectangleType newRect (rx1, ry1, x1 - rx1, ry2 - ry1); isNotEqual (newRect))\r
+                            {\r
+                                r.setX (x1);\r
+                                r.setWidth (rx2 - x1);\r
+\r
+                                rects.insert (++i, newRect);\r
+                                ++i;\r
+                            }\r
                         }\r
                     }\r
-                    else if (x2 > rx1 && x2 < rx2)\r
+                    else if (rx1 < x2 && x2 < rx2)\r
                     {\r
                         r.setX (x2);\r
                         r.setWidth (rx2 - x2);\r
 \r
-                        if (y1 > ry1 || y2 < ry2 || x1 > rx1)\r
+                        if (ry1 < y1 || y2 < ry2 || rx1 < x1)\r
                         {\r
-                            rects.insert (++i, RectangleType (rx1, ry1, x2 - rx1,  ry2 - ry1));\r
-                            ++i;\r
+                            if (const RectangleType newRect (rx1, ry1, x2 - rx1, ry2 - ry1); isNotEqual (newRect))\r
+                            {\r
+                                rects.insert (++i, newRect);\r
+                                ++i;\r
+                            }\r
                         }\r
                     }\r
-                    else if (y1 > ry1 && y1 < ry2)\r
+                    else if (ry1 < y1 && y1 < ry2)\r
                     {\r
-                        if (x1 <= rx1 && x2 >= rx2 && y2 >= ry2)\r
+                        if (x1 <= rx1 && rx2 <= x2 && ry2 <= y2)\r
                         {\r
                             r.setHeight (y1 - ry1);\r
                         }\r
                         else\r
                         {\r
-                            r.setY (y1);\r
-                            r.setHeight (ry2 - y1);\r
-\r
-                            rects.insert (++i, RectangleType (rx1, ry1, rx2 - rx1, y1 - ry1));\r
-                            ++i;\r
+                            if (const RectangleType newRect (rx1, ry1, rx2 - rx1, y1 - ry1); isNotEqual (newRect))\r
+                            {\r
+                                r.setY (y1);\r
+                                r.setHeight (ry2 - y1);\r
+\r
+                                rects.insert (++i, newRect);\r
+                                ++i;\r
+                            }\r
                         }\r
                     }\r
-                    else if (y2 > ry1 && y2 < ry2)\r
+                    else if (ry1 < y2 && y2 < ry2)\r
                     {\r
                         r.setY (y2);\r
                         r.setHeight (ry2 - y2);\r
 \r
-                        if (x1 > rx1 || x2 < rx2 || y1 > ry1)\r
+                        if (rx1 < x1 || x2 < rx2 || ry1 < y1)\r
                         {\r
-                            rects.insert (++i, RectangleType (rx1, ry1, rx2 - rx1, y2 - ry1));\r
-                            ++i;\r
+                            if (const RectangleType newRect (rx1, ry1, rx2 - rx1, y2 - ry1); isNotEqual (newRect))\r
+                            {\r
+                                rects.insert (++i, newRect);\r
+                                ++i;\r
+                            }\r
                         }\r
                     }\r
                     else\r
index d10c3ceed9cd2bb3322f78bf786ebe288300bc60..cb86476d61e8a5f4b77e0d51e977becb0b2a6f47 100644 (file)
 \r
   ID:                 juce_graphics\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE graphics classes\r
   description:        Classes for 2D vector graphics, image loading/saving, font handling, etc.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_events\r
   OSXFrameworks:      Cocoa QuartzCore\r
index 2c34fa9e079ef8a8ca8c3f5ad7667fee91e28886..9c4a3cc249b7455456d1349419c84a5160b408b4 100644 (file)
@@ -154,26 +154,17 @@ public:
     //==============================================================================\r
     StringArray findAllFamilyNames() const\r
     {\r
-        StringArray s;\r
+        std::set<String> set;\r
 \r
         for (auto* face : faces)\r
-            s.addIfNotAlreadyThere (face->family);\r
-\r
-        return s;\r
-    }\r
-\r
-    static int indexOfRegularStyle (const StringArray& styles)\r
-    {\r
-        int i = styles.indexOf ("Regular", true);\r
+            set.insert (face->family);\r
 \r
-        if (i >= 0)\r
-            return i;\r
+        StringArray s;\r
 \r
-        for (i = 0; i < styles.size(); ++i)\r
-            if (! (styles[i].containsIgnoreCase ("Bold") || styles[i].containsIgnoreCase ("Italic")))\r
-                return i;\r
+        for (const auto& family : set)\r
+            s.add (family);\r
 \r
-        return -1;\r
+        return s;\r
     }\r
 \r
     StringArray findAllTypefaceStyles (const String& family) const\r
@@ -184,12 +175,7 @@ public:
             if (face->family == family)\r
                 s.addIfNotAlreadyThere (face->style);\r
 \r
-        // try to get a regular style to be first in the list\r
-        auto regular = indexOfRegularStyle (s);\r
-\r
-        if (regular > 0)\r
-            s.strings.swap (0, regular);\r
-\r
+        // scanFontPaths ensures that regular styles are ordered before other styles\r
         return s;\r
     }\r
 \r
@@ -198,9 +184,48 @@ public:
         for (auto& path : paths)\r
         {\r
             for (const auto& iter : RangedDirectoryIterator (File::getCurrentWorkingDirectory().getChildFile (path), true))\r
+            {\r
                 if (iter.getFile().hasFileExtension ("ttf;pfb;pcf;otf"))\r
                     scanFont (iter.getFile());\r
+            }\r
         }\r
+\r
+        std::sort (faces.begin(), faces.end(), [] (const auto* a, const auto* b)\r
+        {\r
+            const auto tie = [] (const KnownTypeface& t)\r
+            {\r
+                // Used to order styles like "Regular", "Roman" etc. before "Bold", "Italic", etc.\r
+                const auto computeStyleNormalcy = [] (const String& style)\r
+                {\r
+                    if (style == "Regular")\r
+                        return 0;\r
+\r
+                    if (style == "Roman")\r
+                        return 1;\r
+\r
+                    if (style == "Book")\r
+                        return 2;\r
+\r
+                    if (style.containsIgnoreCase ("Bold"))\r
+                        return 3;\r
+\r
+                    if (style.containsIgnoreCase ("Italic"))\r
+                        return 4;\r
+\r
+                    return 5;\r
+                };\r
+\r
+                return std::make_tuple (t.family,\r
+                                        computeStyleNormalcy (t.style),\r
+                                        t.style,\r
+                                        t.isSansSerif,\r
+                                        t.isMonospaced,\r
+                                        t.faceIndex,\r
+                                        t.file);\r
+            };\r
+\r
+            return tie (*a) < tie (*b);\r
+        });\r
     }\r
 \r
     void getMonospacedNames (StringArray& monoSpaced) const\r
index d5e9cc13e3e2839f895aa9ab5aa069c1f843e97d..474b136f3fe6388c3a652a776791d72e57da8a22 100644 (file)
@@ -113,99 +113,85 @@ bool TextLayout::createNativeLayout (const AttributedString&)
 //==============================================================================\r
 struct DefaultFontInfo\r
 {\r
-    struct Characteristics\r
-    {\r
-        explicit Characteristics (String nameIn) : name (nameIn) {}\r
-\r
-        Characteristics withStyle (String styleIn) const\r
-        {\r
-            auto copy = *this;\r
-            copy.style = std::move (styleIn);\r
-            return copy;\r
-        }\r
-\r
-        String name, style;\r
-    };\r
-\r
     DefaultFontInfo()\r
-        : defaultSans  (getDefaultSansSerifFontCharacteristics()),\r
-          defaultSerif (getDefaultSerifFontCharacteristics()),\r
-          defaultFixed (getDefaultMonospacedFontCharacteristics())\r
+        : defaultSans  (getDefaultSansSerifFontName()),\r
+          defaultSerif (getDefaultSerifFontName()),\r
+          defaultFixed (getDefaultMonospacedFontName())\r
     {\r
     }\r
 \r
-    Characteristics getRealFontCharacteristics (const String& faceName) const\r
+    String getRealFontName (const String& faceName) const\r
     {\r
         if (faceName == Font::getDefaultSansSerifFontName())    return defaultSans;\r
         if (faceName == Font::getDefaultSerifFontName())        return defaultSerif;\r
         if (faceName == Font::getDefaultMonospacedFontName())   return defaultFixed;\r
 \r
-        return Characteristics { faceName };\r
+        return faceName;\r
     }\r
 \r
-    Characteristics defaultSans, defaultSerif, defaultFixed;\r
+    String defaultSans, defaultSerif, defaultFixed;\r
 \r
 private:\r
     template <typename Range>\r
-    static Characteristics pickBestFont (const StringArray& names, Range&& choicesArray)\r
+    static String pickBestFont (const StringArray& names, Range&& choicesArray)\r
     {\r
         for (auto& choice : choicesArray)\r
-            if (names.contains (choice.name, true))\r
+            if (names.contains (choice, true))\r
                 return choice;\r
 \r
         for (auto& choice : choicesArray)\r
             for (auto& name : names)\r
-                if (name.startsWithIgnoreCase (choice.name))\r
-                    return Characteristics { name }.withStyle (choice.style);\r
+                if (name.startsWithIgnoreCase (choice))\r
+                    return name;\r
 \r
         for (auto& choice : choicesArray)\r
             for (auto& name : names)\r
-                if (name.containsIgnoreCase (choice.name))\r
-                    return Characteristics { name }.withStyle (choice.style);\r
+                if (name.containsIgnoreCase (choice))\r
+                    return name;\r
 \r
-        return Characteristics { names[0] };\r
+        return names[0];\r
     }\r
 \r
-    static Characteristics getDefaultSansSerifFontCharacteristics()\r
+    static String getDefaultSansSerifFontName()\r
     {\r
         StringArray allFonts;\r
         FTTypefaceList::getInstance()->getSansSerifNames (allFonts);\r
 \r
-        static const Characteristics targets[] { Characteristics { "Verdana" },\r
-                                                 Characteristics { "Bitstream Vera Sans" }.withStyle ("Roman"),\r
-                                                 Characteristics { "Luxi Sans" },\r
-                                                 Characteristics { "Liberation Sans" },\r
-                                                 Characteristics { "DejaVu Sans" },\r
-                                                 Characteristics { "Sans" } };\r
+        static constexpr const char* targets[] { "Verdana",\r
+                                                 "Bitstream Vera Sans",\r
+                                                 "Luxi Sans",\r
+                                                 "Liberation Sans",\r
+                                                 "DejaVu Sans",\r
+                                                 "Sans" };\r
         return pickBestFont (allFonts, targets);\r
     }\r
 \r
-    static Characteristics getDefaultSerifFontCharacteristics()\r
+    static String getDefaultSerifFontName()\r
     {\r
         StringArray allFonts;\r
         FTTypefaceList::getInstance()->getSerifNames (allFonts);\r
 \r
-        static const Characteristics targets[] { Characteristics { "Bitstream Vera Serif" }.withStyle ("Roman"),\r
-                                                 Characteristics { "Times" },\r
-                                                 Characteristics { "Nimbus Roman" },\r
-                                                 Characteristics { "Liberation Serif" },\r
-                                                 Characteristics { "DejaVu Serif" },\r
-                                                 Characteristics { "Serif" } };\r
+        static constexpr const char* targets[] { "Bitstream Vera Serif",\r
+                                                 "Times",\r
+                                                 "Nimbus Roman",\r
+                                                 "Liberation Serif",\r
+                                                 "DejaVu Serif",\r
+                                                 "Serif" };\r
         return pickBestFont (allFonts, targets);\r
     }\r
 \r
-    static Characteristics getDefaultMonospacedFontCharacteristics()\r
+    static String getDefaultMonospacedFontName()\r
     {\r
         StringArray allFonts;\r
         FTTypefaceList::getInstance()->getMonospacedNames (allFonts);\r
 \r
-        static const Characteristics targets[] { Characteristics { "DejaVu Sans Mono" },\r
-                                                 Characteristics { "Bitstream Vera Sans Mono" }.withStyle ("Roman"),\r
-                                                 Characteristics { "Sans Mono" },\r
-                                                 Characteristics { "Liberation Mono" },\r
-                                                 Characteristics { "Courier" },\r
-                                                 Characteristics { "DejaVu Mono" },\r
-                                                 Characteristics { "Mono" } };\r
+        static constexpr const char* targets[] { "DejaVu Sans Mono",\r
+                                                 "Bitstream Vera Sans Mono",\r
+                                                 "Sans Mono",\r
+                                                 "Liberation Mono",\r
+                                                 "Courier",\r
+                                                 "DejaVu Mono",\r
+                                                 "Mono" };\r
         return pickBestFont (allFonts, targets);\r
     }\r
 \r
@@ -219,13 +205,13 @@ Typeface::Ptr Font::getDefaultTypefaceForFont (const Font& font)
     Font f (font);\r
 \r
     const auto name = font.getTypefaceName();\r
-    const auto characteristics = defaultInfo.getRealFontCharacteristics (name);\r
-    f.setTypefaceName (characteristics.name);\r
+    const auto realName = defaultInfo.getRealFontName (name);\r
+    f.setTypefaceName (realName);\r
 \r
-    const auto styles = findAllTypefaceStyles (name);\r
+    const auto styles = findAllTypefaceStyles (realName);\r
 \r
     if (! styles.contains (font.getTypefaceStyle()))\r
-        f.setTypefaceStyle (characteristics.style);\r
+        f.setTypefaceStyle (styles[0]);\r
 \r
     return Typeface::createSystemTypefaceFor (f);\r
 }\r
index aa323fa637eb23510b7abbc5096585a3ac7d7763..6230c99c1cc8f39e32fd34aef7b6af0aeab4fc45 100644 (file)
@@ -53,12 +53,18 @@ namespace detail
         void operator() (CGGradientRef ptr) const noexcept { CGGradientRelease (ptr); }\r
     };\r
 \r
+    struct ColorDelete\r
+    {\r
+        void operator() (CGColorRef ptr) const noexcept { CGColorRelease (ptr); }\r
+    };\r
+\r
     //==============================================================================\r
     using ColorSpacePtr = std::unique_ptr<CGColorSpace, ColorSpaceDelete>;\r
     using ContextPtr = std::unique_ptr<CGContext, ContextDelete>;\r
     using DataProviderPtr = std::unique_ptr<CGDataProvider, DataProviderDelete>;\r
     using ImagePtr = std::unique_ptr<CGImage, ImageDelete>;\r
     using GradientPtr = std::unique_ptr<CGGradient, GradientDelete>;\r
+    using ColorPtr = std::unique_ptr<CGColor, ColorDelete>;\r
 }\r
 \r
 //==============================================================================\r
@@ -95,6 +101,7 @@ public:
     void setInterpolationQuality (Graphics::ResamplingQuality) override;\r
 \r
     //==============================================================================\r
+    void fillAll() override;\r
     void fillRect (const Rectangle<int>&, bool replaceExistingContents) override;\r
     void fillRect (const Rectangle<float>&) override;\r
     void fillRectList (const RectangleList<float>&) override;\r
index 7e78c80442a2ae09d8e775a19ee4ff8f1fd6a811..417d16c7f46c0bd932105d9690544dfd1f9411ca 100644 (file)
@@ -404,8 +404,13 @@ void CoreGraphicsContext::setFill (const FillType& fillType)
 \r
     if (fillType.isColour())\r
     {\r
-        CGContextSetRGBFillColor (context.get(), fillType.colour.getFloatRed(), fillType.colour.getFloatGreen(),\r
-                                  fillType.colour.getFloatBlue(), fillType.colour.getFloatAlpha());\r
+        const CGFloat components[] { fillType.colour.getFloatRed(),\r
+                                     fillType.colour.getFloatGreen(),\r
+                                     fillType.colour.getFloatBlue(),\r
+                                     fillType.colour.getFloatAlpha() };\r
+\r
+        const detail::ColorPtr color { CGColorCreate (rgbColourSpace.get(), components) };\r
+        CGContextSetFillColorWithColor (context.get(), color.get());\r
         CGContextSetAlpha (context.get(), 1.0f);\r
     }\r
 }\r
@@ -428,6 +433,26 @@ void CoreGraphicsContext::setInterpolationQuality (Graphics::ResamplingQuality q
 }\r
 \r
 //==============================================================================\r
+void CoreGraphicsContext::fillAll()\r
+{\r
+    // The clip rectangle is expanded in order to avoid having alpha blended pixels at the edges.\r
+    // The clipping mechanism will take care of cutting off pixels beyond the clip bounds. This is\r
+    // a hard cutoff and will ensure that no semi-transparent pixels will remain inside the filled\r
+    // area.\r
+    const auto clipBounds = getClipBounds();\r
+\r
+    const auto clipBoundsOnDevice = CGContextConvertSizeToDeviceSpace (context.get(),\r
+                                                                       CGSize { (CGFloat) clipBounds.getWidth(),\r
+                                                                                (CGFloat) clipBounds.getHeight() });\r
+\r
+    const auto inverseScale = clipBoundsOnDevice.width > (CGFloat) 0.0\r
+                            ? (int) (clipBounds.getWidth() / clipBoundsOnDevice.width)\r
+                            : 0;\r
+    const auto expansion = jmax (1, inverseScale);\r
+\r
+    fillRect (clipBounds.expanded (expansion), false);\r
+}\r
+\r
 void CoreGraphicsContext::fillRect (const Rectangle<int>& r, bool replaceExistingContents)\r
 {\r
     fillCGRect (CGRectMake (r.getX(), flipHeight - r.getBottom(), r.getWidth(), r.getHeight()), replaceExistingContents);\r
index b5e3340f9cd8ed8646bfe82c05c4576148ed8bec..d848addf84530afded315e5d1239a2ad9b929f85 100644 (file)
@@ -528,8 +528,8 @@ Direct2DLowLevelGraphicsContext::Direct2DLowLevelGraphicsContext (HWND hwnd_)
 \r
     if (pimpl->factories->d2dFactory != nullptr)\r
     {\r
-        auto hr = pimpl->factories->d2dFactory->CreateHwndRenderTarget ({}, { hwnd, size }, pimpl->renderingTarget.resetAndGetPointerAddress());\r
-        jassert (SUCCEEDED (hr)); ignoreUnused (hr);\r
+        [[maybe_unused]] auto hr = pimpl->factories->d2dFactory->CreateHwndRenderTarget ({}, { hwnd, size }, pimpl->renderingTarget.resetAndGetPointerAddress());\r
+        jassert (SUCCEEDED (hr));\r
         hr = pimpl->renderingTarget->CreateSolidColorBrush (D2D1::ColorF::ColorF (0.0f, 0.0f, 0.0f, 1.0f), pimpl->colourBrush.resetAndGetPointerAddress());\r
     }\r
 }\r
index b82b4c53516c5b551acdcf8443cf32c0c71a5ec3..f565a58321f4202e6bc5adcbb76590fe41723053 100644 (file)
@@ -200,8 +200,7 @@ namespace DirectWriteTypeLayout
             }\r
 \r
             ComSmartPtr<IDWriteFont> dwFont;\r
-            auto hr = fontCollection.GetFontFromFontFace (glyphRun.fontFace, dwFont.resetAndGetPointerAddress());\r
-            ignoreUnused (hr);\r
+            [[maybe_unused]] auto hr = fontCollection.GetFontFromFontFace (glyphRun.fontFace, dwFont.resetAndGetPointerAddress());\r
             jassert (dwFont != nullptr);\r
 \r
             ComSmartPtr<IDWriteFontFamily> dwFontFamily;\r
@@ -299,8 +298,7 @@ namespace DirectWriteTypeLayout
                 fontIndex = 0;\r
 \r
             ComSmartPtr<IDWriteFontFamily> fontFamily;\r
-            auto hr = fontCollection.GetFontFamily (fontIndex, fontFamily.resetAndGetPointerAddress());\r
-            ignoreUnused (hr);\r
+            [[maybe_unused]] auto hr = fontCollection.GetFontFamily (fontIndex, fontFamily.resetAndGetPointerAddress());\r
 \r
             ComSmartPtr<IDWriteFont> dwFont;\r
             uint32 fontFacesCount = 0;\r
@@ -420,8 +418,7 @@ namespace DirectWriteTypeLayout
             return;\r
 \r
         UINT32 actualLineCount = 0;\r
-        auto hr = dwTextLayout->GetLineMetrics (nullptr, 0, &actualLineCount);\r
-        ignoreUnused (hr);\r
+        [[maybe_unused]] auto hr = dwTextLayout->GetLineMetrics (nullptr, 0, &actualLineCount);\r
 \r
         layout.ensureStorageAllocated ((int) actualLineCount);\r
 \r
@@ -486,7 +483,7 @@ static bool canAllTypefacesAndFontsBeUsedInLayout (const AttributedString& text)
 \r
 #endif\r
 \r
-bool TextLayout::createNativeLayout (const AttributedString& text)\r
+bool TextLayout::createNativeLayout ([[maybe_unused]] const AttributedString& text)\r
 {\r
    #if JUCE_USE_DIRECTWRITE\r
     if (! canAllTypefacesAndFontsBeUsedInLayout (text))\r
@@ -506,8 +503,6 @@ bool TextLayout::createNativeLayout (const AttributedString& text)
 \r
         return true;\r
     }\r
-   #else\r
-    ignoreUnused (text);\r
    #endif\r
 \r
     return false;\r
index da59341e6259ad540f426f42ce065b2f69ca54f4..5da133517a78d1573465405faffc44d608cdc102 100644 (file)
@@ -35,8 +35,7 @@ namespace
 \r
         uint32 index = 0;\r
         BOOL exists = false;\r
-        auto hr = names->FindLocaleName (L"en-us", &index, &exists);\r
-        ignoreUnused (hr);\r
+        [[maybe_unused]] auto hr = names->FindLocaleName (L"en-us", &index, &exists);\r
 \r
         if (! exists)\r
             index = 0;\r
@@ -152,8 +151,7 @@ public:
         jassert (fontCollection != nullptr);\r
 \r
         uint32 fontIndex = 0;\r
-        auto hr = fontCollection->FindFamilyName (font.getTypefaceName().toWideCharPointer(), &fontIndex, &fontFound);\r
-        ignoreUnused (hr);\r
+        [[maybe_unused]] auto hr = fontCollection->FindFamilyName (font.getTypefaceName().toWideCharPointer(), &fontIndex, &fontFound);\r
 \r
         if (! fontFound)\r
             fontIndex = 0;\r
index b7d4afe2486d922356a1b52c4d1385234ad908da..005061efb47e496585920a1e16569da78fa22109 100644 (file)
@@ -234,8 +234,7 @@ StringArray Font::findAllTypefaceStyles (const String& family)
     {\r
         BOOL fontFound = false;\r
         uint32 fontIndex = 0;\r
-        auto hr = factories->systemFonts->FindFamilyName (family.toWideCharPointer(), &fontIndex, &fontFound);\r
-        ignoreUnused (hr);\r
+        [[maybe_unused]] auto hr = factories->systemFonts->FindFamilyName (family.toWideCharPointer(), &fontIndex, &fontFound);\r
 \r
         if (! fontFound)\r
             fontIndex = 0;\r
index 247a6c83c792ca3ce665a88a3c9ae42f9689cc1d..75c1e1dd544e3b735c444ed7084a11474f4dc110 100644 (file)
@@ -50,73 +50,73 @@ public:
 \r
         @see isCheckable\r
     */\r
-    JUCE_NODISCARD AccessibleState withCheckable() const noexcept            { return withFlag (Flags::checkable); }\r
+    [[nodiscard]] AccessibleState withCheckable() const noexcept            { return withFlag (Flags::checkable); }\r
 \r
     /** Sets the checked flag and returns the new state.\r
 \r
         @see isChecked\r
     */\r
-    JUCE_NODISCARD AccessibleState withChecked() const noexcept              { return withFlag (Flags::checked); }\r
+    [[nodiscard]] AccessibleState withChecked() const noexcept              { return withFlag (Flags::checked); }\r
 \r
     /** Sets the collapsed flag and returns the new state.\r
 \r
         @see isCollapsed\r
     */\r
-    JUCE_NODISCARD AccessibleState withCollapsed() const noexcept            { return withFlag (Flags::collapsed); }\r
+    [[nodiscard]] AccessibleState withCollapsed() const noexcept            { return withFlag (Flags::collapsed); }\r
 \r
     /** Sets the expandable flag and returns the new state.\r
 \r
         @see isExpandable\r
     */\r
-    JUCE_NODISCARD AccessibleState withExpandable() const noexcept           { return withFlag (Flags::expandable); }\r
+    [[nodiscard]] AccessibleState withExpandable() const noexcept           { return withFlag (Flags::expandable); }\r
 \r
     /** Sets the expanded flag and returns the new state.\r
 \r
         @see isExpanded\r
     */\r
-    JUCE_NODISCARD AccessibleState withExpanded() const noexcept             { return withFlag (Flags::expanded); }\r
+    [[nodiscard]] AccessibleState withExpanded() const noexcept             { return withFlag (Flags::expanded); }\r
 \r
     /** Sets the focusable flag and returns the new state.\r
 \r
         @see isFocusable\r
     */\r
-    JUCE_NODISCARD AccessibleState withFocusable() const noexcept            { return withFlag (Flags::focusable); }\r
+    [[nodiscard]] AccessibleState withFocusable() const noexcept            { return withFlag (Flags::focusable); }\r
 \r
     /** Sets the focused flag and returns the new state.\r
 \r
         @see isFocused\r
     */\r
-    JUCE_NODISCARD AccessibleState withFocused() const noexcept              { return withFlag (Flags::focused); }\r
+    [[nodiscard]] AccessibleState withFocused() const noexcept              { return withFlag (Flags::focused); }\r
 \r
     /** Sets the ignored flag and returns the new state.\r
 \r
         @see isIgnored\r
     */\r
-    JUCE_NODISCARD AccessibleState withIgnored() const noexcept              { return withFlag (Flags::ignored); }\r
+    [[nodiscard]] AccessibleState withIgnored() const noexcept              { return withFlag (Flags::ignored); }\r
 \r
     /** Sets the selectable flag and returns the new state.\r
 \r
         @see isSelectable\r
     */\r
-    JUCE_NODISCARD AccessibleState withSelectable() const noexcept           { return withFlag (Flags::selectable); }\r
+    [[nodiscard]] AccessibleState withSelectable() const noexcept           { return withFlag (Flags::selectable); }\r
 \r
     /** Sets the multiSelectable flag and returns the new state.\r
 \r
         @see isMultiSelectable\r
     */\r
-    JUCE_NODISCARD AccessibleState withMultiSelectable() const noexcept      { return withFlag (Flags::multiSelectable); }\r
+    [[nodiscard]] AccessibleState withMultiSelectable() const noexcept      { return withFlag (Flags::multiSelectable); }\r
 \r
     /** Sets the selected flag and returns the new state.\r
 \r
         @see isSelected\r
     */\r
-    JUCE_NODISCARD AccessibleState withSelected() const noexcept             { return withFlag (Flags::selected); }\r
+    [[nodiscard]] AccessibleState withSelected() const noexcept             { return withFlag (Flags::selected); }\r
 \r
     /** Sets the accessible offscreen flag and returns the new state.\r
 \r
         @see isSelected\r
     */\r
-    JUCE_NODISCARD AccessibleState withAccessibleOffscreen() const noexcept  { return withFlag (Flags::accessibleOffscreen); }\r
+    [[nodiscard]] AccessibleState withAccessibleOffscreen() const noexcept  { return withFlag (Flags::accessibleOffscreen); }\r
 \r
     //==============================================================================\r
     /** Returns true if the UI element is checkable.\r
@@ -208,7 +208,7 @@ private:
         accessibleOffscreen = (1 << 11)\r
     };\r
 \r
-    JUCE_NODISCARD AccessibleState withFlag (int flag) const noexcept\r
+    [[nodiscard]] AccessibleState withFlag (int flag) const noexcept\r
     {\r
         auto copy = *this;\r
         copy.flags |= flag;\r
index cc7577c5dbbeab9d55e06c5f58c2ba73f61db616..9f8d9d7426b02681fce3efc8f56ccd89c172ed8c 100644 (file)
@@ -39,6 +39,51 @@ static Component* findFirstEnabledAncestor (Component* in)
 \r
 Component* Component::currentlyFocusedComponent = nullptr;\r
 \r
+//==============================================================================\r
+class HierarchyChecker\r
+{\r
+public:\r
+    HierarchyChecker (Component* comp, const MouseEvent& originalEvent)\r
+        : me (originalEvent)\r
+    {\r
+        for (; comp != nullptr; comp = comp->getParentComponent())\r
+            hierarchy.emplace_back (comp);\r
+    }\r
+\r
+    Component* nearestNonNullParent() const\r
+    {\r
+        for (auto& comp : hierarchy)\r
+            if (comp != nullptr)\r
+                return comp;\r
+\r
+        return nullptr;\r
+    }\r
+\r
+    bool shouldBailOut() const\r
+    {\r
+        return nearestNonNullParent() == nullptr;\r
+    }\r
+\r
+    MouseEvent eventWithNearestParent() const\r
+    {\r
+        auto* comp = nearestNonNullParent();\r
+        return { me.source,\r
+                 me.position.toFloat(),\r
+                 me.mods,\r
+                 me.pressure, me.orientation, me.rotation,\r
+                 me.tiltX, me.tiltY,\r
+                 comp, comp,\r
+                 me.eventTime,\r
+                 me.mouseDownPosition.toFloat(),\r
+                 me.mouseDownTime,\r
+                 me.getNumberOfClicks(),\r
+                 me.mouseWasDraggedSinceMouseDown() };\r
+    }\r
+\r
+private:\r
+    std::vector<Component::SafePointer<Component>> hierarchy;\r
+    const MouseEvent me;\r
+};\r
 \r
 //==============================================================================\r
 class Component::MouseListenerList\r
@@ -75,104 +120,41 @@ public:
         }\r
     }\r
 \r
-    // g++ 4.8 cannot deduce the parameter pack inside the function pointer when it has more than one element\r
-   #if defined(__GNUC__) && __GNUC__ < 5 && ! defined(__clang__)\r
-    template <typename... Params>\r
-    static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
-                                void (MouseListener::*eventMethod) (const MouseEvent&),\r
-                                Params... params)\r
-    {\r
-        sendMouseEvent <decltype (eventMethod), Params...> (comp, checker, eventMethod, params...);\r
-    }\r
-\r
-    template <typename... Params>\r
-    static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
-                                void (MouseListener::*eventMethod) (const MouseEvent&, const MouseWheelDetails&),\r
-                                Params... params)\r
-    {\r
-        sendMouseEvent <decltype (eventMethod), Params...> (comp, checker, eventMethod, params...);\r
-    }\r
-\r
-    template <typename... Params>\r
-    static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
-                                void (MouseListener::*eventMethod) (const MouseEvent&, float),\r
-                                Params... params)\r
-    {\r
-        sendMouseEvent <decltype (eventMethod), Params...> (comp, checker, eventMethod, params...);\r
-    }\r
-\r
     template <typename EventMethod, typename... Params>\r
-    static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
-                                EventMethod eventMethod,\r
-                                Params... params)\r
-   #else\r
-    template <typename... Params>\r
-    static void sendMouseEvent (Component& comp, Component::BailOutChecker& checker,\r
-                                void (MouseListener::*eventMethod) (Params...),\r
-                                Params... params)\r
-   #endif\r
+    static void sendMouseEvent (HierarchyChecker& checker, EventMethod&& eventMethod, Params&&... params)\r
     {\r
-        if (checker.shouldBailOut())\r
-            return;\r
-\r
-        if (auto* list = comp.mouseListeners.get())\r
+        const auto callListeners = [&] (auto& parentComp, const auto findNumListeners)\r
         {\r
-            for (int i = list->listeners.size(); --i >= 0;)\r
+            if (auto* list = parentComp.mouseListeners.get())\r
             {\r
-                (list->listeners.getUnchecked(i)->*eventMethod) (params...);\r
+                const WeakReference safePointer { &parentComp };\r
 \r
-                if (checker.shouldBailOut())\r
-                    return;\r
+                for (int i = findNumListeners (*list); --i >= 0; i = jmin (i, findNumListeners (*list)))\r
+                {\r
+                    (list->listeners.getUnchecked (i)->*eventMethod) (checker.eventWithNearestParent(), params...);\r
 \r
-                i = jmin (i, list->listeners.size());\r
+                    if (checker.shouldBailOut() || safePointer == nullptr)\r
+                        return false;\r
+                }\r
             }\r
-        }\r
 \r
-        for (Component* p = comp.parentComponent; p != nullptr; p = p->parentComponent)\r
-        {\r
-            if (auto* list = p->mouseListeners.get())\r
-            {\r
-                if (list->numDeepMouseListeners > 0)\r
-                {\r
-                    BailOutChecker2 checker2 (checker, p);\r
-\r
-                    for (int i = list->numDeepMouseListeners; --i >= 0;)\r
-                    {\r
-                        (list->listeners.getUnchecked(i)->*eventMethod) (params...);\r
+            return true;\r
+        };\r
 \r
-                        if (checker2.shouldBailOut())\r
-                            return;\r
+        if (auto* parent = checker.nearestNonNullParent())\r
+            if (! callListeners (*parent, [] (auto& list) { return list.listeners.size(); }))\r
+                return;\r
 \r
-                        i = jmin (i, list->numDeepMouseListeners);\r
-                    }\r
-                }\r
-            }\r
-        }\r
+        if (auto* parent = checker.nearestNonNullParent())\r
+            for (Component* p = parent->parentComponent; p != nullptr; p = p->parentComponent)\r
+                if (! callListeners (*p, [] (auto& list) { return list.numDeepMouseListeners; }))\r
+                    return;\r
     }\r
 \r
 private:\r
     Array<MouseListener*> listeners;\r
     int numDeepMouseListeners = 0;\r
 \r
-    struct BailOutChecker2\r
-    {\r
-        BailOutChecker2 (Component::BailOutChecker& boc, Component* comp)\r
-            : checker (boc), safePointer (comp)\r
-        {\r
-        }\r
-\r
-        bool shouldBailOut() const noexcept\r
-        {\r
-            return checker.shouldBailOut() || safePointer == nullptr;\r
-        }\r
-\r
-    private:\r
-        Component::BailOutChecker& checker;\r
-        const WeakReference<Component> safePointer;\r
-\r
-        JUCE_DECLARE_NON_COPYABLE (BailOutChecker2)\r
-    };\r
-\r
     JUCE_DECLARE_NON_COPYABLE (MouseListenerList)\r
 };\r
 \r
@@ -1769,6 +1751,8 @@ void Component::enterModalState (bool shouldTakeKeyboardFocus,
     // thread, you'll need to use a MessageManagerLock object to make sure it's thread-safe.\r
     JUCE_ASSERT_MESSAGE_MANAGER_IS_LOCKED\r
 \r
+    SafePointer safeReference { this };\r
+\r
     if (! isCurrentlyModal (false))\r
     {\r
         // While this component is in modal state it may block other components from receiving\r
@@ -1776,6 +1760,13 @@ void Component::enterModalState (bool shouldTakeKeyboardFocus,
         // we must manually force the mouse to "leave" blocked components.\r
         ComponentHelpers::sendMouseEventToComponentsThatAreBlockedByModal (*this, &Component::internalMouseExit);\r
 \r
+        if (safeReference == nullptr)\r
+        {\r
+            // If you hit this assertion, the mouse-exit event above has caused the modal component to be deleted.\r
+            jassertfalse;\r
+            return;\r
+        }\r
+\r
         auto& mcm = *ModalComponentManager::getInstance();\r
         mcm.startModal (this, deleteWhenDismissed);\r
         mcm.attachCallback (this, callback);\r
@@ -2413,8 +2404,6 @@ void Component::internalMouseEnter (MouseInputSource source, Point<float> relati
     if (flags.repaintOnMouseActivityFlag)\r
         repaint();\r
 \r
-    BailOutChecker checker (this);\r
-\r
     const auto me = makeMouseEvent (source,\r
                                     PointerState().withPosition (relativePos),\r
                                     source.getCurrentModifiers(),\r
@@ -2425,6 +2414,8 @@ void Component::internalMouseEnter (MouseInputSource source, Point<float> relati
                                     time,\r
                                     0,\r
                                     false);\r
+\r
+    HierarchyChecker checker (this, me);\r
     mouseEnter (me);\r
 \r
     flags.cachedMouseInsideComponent = true;\r
@@ -2433,8 +2424,7 @@ void Component::internalMouseEnter (MouseInputSource source, Point<float> relati
         return;\r
 \r
     Desktop::getInstance().getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseEnter (me); });\r
-\r
-    MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseEnter, me);\r
+    MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseEnter);\r
 }\r
 \r
 void Component::internalMouseExit (MouseInputSource source, Point<float> relativePos, Time time)\r
@@ -2451,8 +2441,6 @@ void Component::internalMouseExit (MouseInputSource source, Point<float> relativ
 \r
     flags.cachedMouseInsideComponent = false;\r
 \r
-    BailOutChecker checker (this);\r
-\r
     const auto me = makeMouseEvent (source,\r
                                     PointerState().withPosition (relativePos),\r
                                     source.getCurrentModifiers(),\r
@@ -2464,20 +2452,32 @@ void Component::internalMouseExit (MouseInputSource source, Point<float> relativ
                                     0,\r
                                     false);\r
 \r
+    HierarchyChecker checker (this, me);\r
     mouseExit (me);\r
 \r
     if (checker.shouldBailOut())\r
         return;\r
 \r
     Desktop::getInstance().getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseExit (me); });\r
-\r
-    MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseExit, me);\r
+    MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseExit);\r
 }\r
 \r
 void Component::internalMouseDown (MouseInputSource source, const PointerState& relativePointerState, Time time)\r
 {\r
     auto& desktop = Desktop::getInstance();\r
-    BailOutChecker checker (this);\r
+\r
+    const auto me = makeMouseEvent (source,\r
+                                    relativePointerState,\r
+                                    source.getCurrentModifiers(),\r
+                                    this,\r
+                                    this,\r
+                                    time,\r
+                                    relativePointerState.position,\r
+                                    time,\r
+                                    source.getNumberOfMultipleClicks(),\r
+                                    false);\r
+\r
+    HierarchyChecker checker (this, me);\r
 \r
     if (isCurrentlyBlockedByAnotherModalComponent())\r
     {\r
@@ -2492,18 +2492,7 @@ void Component::internalMouseDown (MouseInputSource source, const PointerState&
         if (isCurrentlyBlockedByAnotherModalComponent())\r
         {\r
             // allow blocked mouse-events to go to global listeners..\r
-            const auto me = makeMouseEvent (source,\r
-                                            relativePointerState,\r
-                                            source.getCurrentModifiers(),\r
-                                            this,\r
-                                            this,\r
-                                            time,\r
-                                            relativePointerState.position,\r
-                                            time,\r
-                                            source.getNumberOfMultipleClicks(),\r
-                                            false);\r
-\r
-            desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDown (me); });\r
+            desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDown (checker.eventWithNearestParent()); });\r
             return;\r
         }\r
     }\r
@@ -2532,24 +2521,14 @@ void Component::internalMouseDown (MouseInputSource source, const PointerState&
     if (flags.repaintOnMouseActivityFlag)\r
         repaint();\r
 \r
-    const auto me = makeMouseEvent (source,\r
-                                    relativePointerState,\r
-                                    source.getCurrentModifiers(),\r
-                                    this,\r
-                                    this,\r
-                                    time,\r
-                                    relativePointerState.position,\r
-                                    time,\r
-                                    source.getNumberOfMultipleClicks(),\r
-                                    false);\r
     mouseDown (me);\r
 \r
     if (checker.shouldBailOut())\r
         return;\r
 \r
-    desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDown (me); });\r
+    desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDown (checker.eventWithNearestParent()); });\r
 \r
-    MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseDown, me);\r
+    MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseDown);\r
 }\r
 \r
 void Component::internalMouseUp (MouseInputSource source, const PointerState& relativePointerState, Time time, const ModifierKeys oldModifiers)\r
@@ -2557,11 +2536,6 @@ void Component::internalMouseUp (MouseInputSource source, const PointerState& re
     if (flags.mouseDownWasBlocked && isCurrentlyBlockedByAnotherModalComponent())\r
         return;\r
 \r
-    BailOutChecker checker (this);\r
-\r
-    if (flags.repaintOnMouseActivityFlag)\r
-        repaint();\r
-\r
     const auto me = makeMouseEvent (source,\r
                                     relativePointerState,\r
                                     oldModifiers,\r
@@ -2572,15 +2546,21 @@ void Component::internalMouseUp (MouseInputSource source, const PointerState& re
                                     source.getLastMouseDownTime(),\r
                                     source.getNumberOfMultipleClicks(),\r
                                     source.isLongPressOrDrag());\r
+\r
+    HierarchyChecker checker (this, me);\r
+\r
+    if (flags.repaintOnMouseActivityFlag)\r
+        repaint();\r
+\r
     mouseUp (me);\r
 \r
     if (checker.shouldBailOut())\r
         return;\r
 \r
     auto& desktop = Desktop::getInstance();\r
-    desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseUp (me); });\r
+    desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseUp (checker.eventWithNearestParent()); });\r
 \r
-    MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseUp, me);\r
+    MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseUp);\r
 \r
     if (checker.shouldBailOut())\r
         return;\r
@@ -2588,13 +2568,14 @@ void Component::internalMouseUp (MouseInputSource source, const PointerState& re
     // check for double-click\r
     if (me.getNumberOfClicks() >= 2)\r
     {\r
-        mouseDoubleClick (me);\r
+        if (checker.nearestNonNullParent() == this)\r
+            mouseDoubleClick (checker.eventWithNearestParent());\r
 \r
         if (checker.shouldBailOut())\r
             return;\r
 \r
-        desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseDoubleClick (me); });\r
-        MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseDoubleClick, me);\r
+        desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseDoubleClick (checker.eventWithNearestParent()); });\r
+        MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseDoubleClick);\r
     }\r
 }\r
 \r
@@ -2602,8 +2583,6 @@ void Component::internalMouseDrag (MouseInputSource source, const PointerState&
 {\r
     if (! isCurrentlyBlockedByAnotherModalComponent())\r
     {\r
-        BailOutChecker checker (this);\r
-\r
         const auto me = makeMouseEvent (source,\r
                                         relativePointerState,\r
                                         source.getCurrentModifiers(),\r
@@ -2614,14 +2593,16 @@ void Component::internalMouseDrag (MouseInputSource source, const PointerState&
                                         source.getLastMouseDownTime(),\r
                                         source.getNumberOfMultipleClicks(),\r
                                         source.isLongPressOrDrag());\r
+\r
+        HierarchyChecker checker (this, me);\r
+\r
         mouseDrag (me);\r
 \r
         if (checker.shouldBailOut())\r
             return;\r
 \r
-        Desktop::getInstance().getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDrag (me); });\r
-\r
-        MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseDrag, me);\r
+        Desktop::getInstance().getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseDrag (checker.eventWithNearestParent()); });\r
+        MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseDrag);\r
     }\r
 }\r
 \r
@@ -2636,8 +2617,6 @@ void Component::internalMouseMove (MouseInputSource source, Point<float> relativ
     }\r
     else\r
     {\r
-        BailOutChecker checker (this);\r
-\r
         const auto me = makeMouseEvent (source,\r
                                         PointerState().withPosition (relativePos),\r
                                         source.getCurrentModifiers(),\r
@@ -2648,14 +2627,16 @@ void Component::internalMouseMove (MouseInputSource source, Point<float> relativ
                                         time,\r
                                         0,\r
                                         false);\r
+\r
+        HierarchyChecker checker (this, me);\r
+\r
         mouseMove (me);\r
 \r
         if (checker.shouldBailOut())\r
             return;\r
 \r
-        desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseMove (me); });\r
-\r
-        MouseListenerList::template sendMouseEvent<const MouseEvent&> (*this, checker, &MouseListener::mouseMove, me);\r
+        desktop.getMouseListeners().callChecked (checker, [&] (MouseListener& l) { l.mouseMove (checker.eventWithNearestParent()); });\r
+        MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseMove);\r
     }\r
 }\r
 \r
@@ -2663,7 +2644,6 @@ void Component::internalMouseWheel (MouseInputSource source, Point<float> relati
                                     Time time, const MouseWheelDetails& wheel)\r
 {\r
     auto& desktop = Desktop::getInstance();\r
-    BailOutChecker checker (this);\r
 \r
     const auto me = makeMouseEvent (source,\r
                                     PointerState().withPosition (relativePos),\r
@@ -2676,6 +2656,8 @@ void Component::internalMouseWheel (MouseInputSource source, Point<float> relati
                                     0,\r
                                     false);\r
 \r
+    HierarchyChecker checker (this, me);\r
+\r
     if (isCurrentlyBlockedByAnotherModalComponent())\r
     {\r
         // allow blocked mouse-events to go to global listeners..\r
@@ -2688,10 +2670,10 @@ void Component::internalMouseWheel (MouseInputSource source, Point<float> relati
         if (checker.shouldBailOut())\r
             return;\r
 \r
-        desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseWheelMove (me, wheel); });\r
+        desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseWheelMove (checker.eventWithNearestParent(), wheel); });\r
 \r
         if (! checker.shouldBailOut())\r
-            MouseListenerList::template sendMouseEvent<const MouseEvent&, const MouseWheelDetails&> (*this, checker, &MouseListener::mouseWheelMove, me, wheel);\r
+            MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseWheelMove, wheel);\r
     }\r
 }\r
 \r
@@ -2699,7 +2681,6 @@ void Component::internalMagnifyGesture (MouseInputSource source, Point<float> re
                                         Time time, float amount)\r
 {\r
     auto& desktop = Desktop::getInstance();\r
-    BailOutChecker checker (this);\r
 \r
     const auto me = makeMouseEvent (source,\r
                                     PointerState().withPosition (relativePos),\r
@@ -2712,6 +2693,8 @@ void Component::internalMagnifyGesture (MouseInputSource source, Point<float> re
                                     0,\r
                                     false);\r
 \r
+    HierarchyChecker checker (this, me);\r
+\r
     if (isCurrentlyBlockedByAnotherModalComponent())\r
     {\r
         // allow blocked mouse-events to go to global listeners..\r
@@ -2724,10 +2707,10 @@ void Component::internalMagnifyGesture (MouseInputSource source, Point<float> re
         if (checker.shouldBailOut())\r
             return;\r
 \r
-        desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseMagnify (me, amount); });\r
+        desktop.mouseListeners.callChecked (checker, [&] (MouseListener& l) { l.mouseMagnify (checker.eventWithNearestParent(), amount); });\r
 \r
         if (! checker.shouldBailOut())\r
-            MouseListenerList::template sendMouseEvent<const MouseEvent&, float> (*this, checker, &MouseListener::mouseMagnify, me, amount);\r
+            MouseListenerList::sendMouseEvent (checker, &MouseListener::mouseMagnify, amount);\r
     }\r
 }\r
 \r
index 24529bf5358bb0028b717695bbf83b75c51114b8..9f7304969532ae9cc3f1a00f14f641c5dd5563f8 100644 (file)
@@ -2132,7 +2132,7 @@ public:
 \r
         @see runModalLoop, enterModalState, isCurrentlyModal\r
     */\r
-    void exitModalState (int returnValue);\r
+    void exitModalState (int returnValue = 0);\r
 \r
     /** Returns true if this component is the modal one.\r
 \r
index 9108d5a98341c013e48589fa0d74159a692871e8..75bba0dbe5ce18903021f92b588c179f8437594f 100644 (file)
@@ -93,6 +93,12 @@ public:
             pixels per inch, divide this by the Display::scale value.\r
         */\r
         double dpi;\r
+\r
+        /** The vertical refresh rate of the display if applicable.\r
+\r
+            Currently this is only used on Linux for display rate repainting.\r
+        */\r
+        std::optional<double> verticalFrequencyHz;\r
     };\r
 \r
     //==============================================================================\r
index 9887b1c363a0cbd4e588ee2eac281c622539c069..eb1c7514d27ac7ed5ef38334868dde63915fcf85 100644 (file)
@@ -150,15 +150,13 @@ JUCE_IMPLEMENT_SINGLETON (ContentSharer)
 ContentSharer::ContentSharer() {}\r
 ContentSharer::~ContentSharer() { clearSingletonInstance(); }\r
 \r
-void ContentSharer::shareFiles (const Array<URL>& files,\r
+void ContentSharer::shareFiles ([[maybe_unused]] const Array<URL>& files,\r
                                 std::function<void (bool, const String&)> callbackToUse)\r
 {\r
   #if JUCE_CONTENT_SHARING\r
     startNewShare (callbackToUse);\r
     pimpl->shareFiles (files);\r
   #else\r
-    ignoreUnused (files);\r
-\r
     // Content sharing is not available on this platform!\r
     jassertfalse;\r
 \r
@@ -188,15 +186,13 @@ void ContentSharer::startNewShare (std::function<void (bool, const String&)> cal
 }\r
 #endif\r
 \r
-void ContentSharer::shareText (const String& text,\r
+void ContentSharer::shareText ([[maybe_unused]] const String& text,\r
                                std::function<void (bool, const String&)> callbackToUse)\r
 {\r
   #if JUCE_CONTENT_SHARING\r
     startNewShare (callbackToUse);\r
     pimpl->shareText (text);\r
   #else\r
-    ignoreUnused (text);\r
-\r
     // Content sharing is not available on this platform!\r
     jassertfalse;\r
 \r
@@ -205,16 +201,14 @@ void ContentSharer::shareText (const String& text,
   #endif\r
 }\r
 \r
-void ContentSharer::shareImages (const Array<Image>& images,\r
+void ContentSharer::shareImages ([[maybe_unused]] const Array<Image>& images,\r
                                  std::function<void (bool, const String&)> callbackToUse,\r
-                                 ImageFileFormat* imageFileFormatToUse)\r
+                                 [[maybe_unused]] ImageFileFormat* imageFileFormatToUse)\r
 {\r
   #if JUCE_CONTENT_SHARING\r
     startNewShare (callbackToUse);\r
     prepareImagesThread.reset (new PrepareImagesThread (*this, images, imageFileFormatToUse));\r
   #else\r
-    ignoreUnused (images, imageFileFormatToUse);\r
-\r
     // Content sharing is not available on this platform!\r
     jassertfalse;\r
 \r
@@ -238,15 +232,13 @@ void ContentSharer::filesToSharePrepared()
 }\r
 #endif\r
 \r
-void ContentSharer::shareData (const MemoryBlock& mb,\r
+void ContentSharer::shareData ([[maybe_unused]] const MemoryBlock& mb,\r
                                std::function<void (bool, const String&)> callbackToUse)\r
 {\r
   #if JUCE_CONTENT_SHARING\r
     startNewShare (callbackToUse);\r
     prepareDataThread.reset (new PrepareDataThread (*this, mb));\r
   #else\r
-    ignoreUnused (mb);\r
-\r
     if (callbackToUse)\r
         callbackToUse (false, "Content sharing not available on this platform!");\r
   #endif\r
index 134e4511911520ba3f2cb19cda7767c3e7656e01..75a9f1ddbcfa9737608817012e7af0f0dce2c1e1 100644 (file)
@@ -27,7 +27,7 @@ namespace juce
 {\r
 \r
 DirectoryContentsList::DirectoryContentsList (const FileFilter* f, TimeSliceThread& t)\r
-   : fileFilter (f), thread (t)\r
+    : fileFilter (f), thread (t)\r
 {\r
 }\r
 \r
@@ -202,33 +202,27 @@ int DirectoryContentsList::useTimeSlice()
 \r
 bool DirectoryContentsList::checkNextFile (bool& hasChanged)\r
 {\r
-    if (fileFindHandle != nullptr)\r
-    {\r
-        if (*fileFindHandle != RangedDirectoryIterator())\r
-        {\r
-            const auto entry = *(*fileFindHandle)++;\r
-\r
-            if (addFile (entry.getFile(),\r
-                         entry.isDirectory(),\r
-                         entry.getFileSize(),\r
-                         entry.getModificationTime(),\r
-                         entry.getCreationTime(),\r
-                         entry.isReadOnly()))\r
-            {\r
-                hasChanged = true;\r
-            }\r
-\r
-            return true;\r
-        }\r
+    if (fileFindHandle == nullptr)\r
+        return false;\r
 \r
+    if (*fileFindHandle == RangedDirectoryIterator())\r
+    {\r
         fileFindHandle = nullptr;\r
         isSearching = false;\r
-\r
-        if (! wasEmpty && files.isEmpty())\r
-            hasChanged = true;\r
+        hasChanged = true;\r
+        return false;\r
     }\r
 \r
-    return false;\r
+    const auto entry = *(*fileFindHandle)++;\r
+\r
+    hasChanged |= addFile (entry.getFile(),\r
+                           entry.isDirectory(),\r
+                           entry.getFileSize(),\r
+                           entry.getModificationTime(),\r
+                           entry.getCreationTime(),\r
+                           entry.isReadOnly());\r
+\r
+    return true;\r
 }\r
 \r
 bool DirectoryContentsList::addFile (const File& file, const bool isDir,\r
index 39f337f4c51ca7749f132f1c5ced0ba85e28b77e..13e4f9d764b4169e5bba7954d92e18a6409b30a0 100644 (file)
@@ -63,6 +63,9 @@ FileBrowserComponent::FileBrowserComponent (int flags_,
         filename = initialFileOrDirectory.getFileName();\r
     }\r
 \r
+    // The thread must be started before the DirectoryContentsList attempts to scan any file\r
+    thread.startThread (Thread::Priority::low);\r
+\r
     fileList.reset (new DirectoryContentsList (this, thread));\r
     fileList->setDirectory (currentRoot, true, true);\r
 \r
@@ -122,8 +125,6 @@ FileBrowserComponent::FileBrowserComponent (int flags_,
     if (filename.isNotEmpty())\r
         setFileName (filename);\r
 \r
-    thread.startThread (4);\r
-\r
     startTimer (2000);\r
 }\r
 \r
@@ -439,7 +440,7 @@ void FileBrowserComponent::fileDoubleClicked (const File& f)
 \r
 void FileBrowserComponent::browserRootChanged (const File&) {}\r
 \r
-bool FileBrowserComponent::keyPressed (const KeyPress& key)\r
+bool FileBrowserComponent::keyPressed ([[maybe_unused]] const KeyPress& key)\r
 {\r
    #if JUCE_LINUX || JUCE_BSD || JUCE_WINDOWS\r
     if (key.getModifiers().isCommandDown()\r
@@ -451,7 +452,6 @@ bool FileBrowserComponent::keyPressed (const KeyPress& key)
     }\r
    #endif\r
 \r
-    ignoreUnused (key);\r
     return false;\r
 }\r
 \r
index 10224c49e41ca294530ecab7183ac33432fb2848..a85f57ee1686870b9a47d869573f4d24f9602c26 100644 (file)
@@ -270,6 +270,13 @@ void FileChooser::finished (const Array<URL>& asyncResults)
          callback (*this);\r
 }\r
 \r
+#if ! JUCE_ANDROID\r
+void FileChooser::registerCustomMimeTypeForFileExtension ([[maybe_unused]] const String& mimeType,\r
+                                                          [[maybe_unused]] const String& fileExtension)\r
+{\r
+}\r
+#endif\r
+\r
 //==============================================================================\r
 FilePreviewComponent::FilePreviewComponent() {}\r
 FilePreviewComponent::~FilePreviewComponent() {}\r
index b9242e9c06e4ab9c3138c587350024685d77fbe8..c19b9bfbc98c0d915388ea8855d86dc8a334266b 100644 (file)
@@ -293,6 +293,19 @@ public:
     */\r
     static bool isPlatformDialogAvailable();\r
 \r
+    /** Associate a particular file-extension to a mime-type\r
+\r
+        On Android, JUCE needs to convert common file extensions to mime-types when using\r
+        wildcard filters in native file chooser dialog boxes. JUCE has an extensive conversion\r
+        table to convert between the most common file-types and mime-types transparently, but\r
+        some more obscure file-types may be missing. Use this method to register your own\r
+        mime-type to file extension conversions. Please contact the JUCE team if you think\r
+        that a common mime-type/file-extension entry is missing in JUCE's internal tables.\r
+        Does nothing on other platforms.\r
+    */\r
+    static void registerCustomMimeTypeForFileExtension (const String& mimeType,\r
+                                                        const String& fileExtension);\r
+\r
     //==============================================================================\r
    #ifndef DOXYGEN\r
     class Native;\r
index 904dac3c36e9a78abc46839309c411bdbdfbfcca..bf1e147de5ae79baa0015e93ec13116bef42f718 100644 (file)
@@ -60,7 +60,7 @@ namespace juce
         dialogBox->centreWithDefaultSize (nullptr);\r
         dialogBox->enterModalState (true,\r
                                     ModalCallbackFunction::create (onFileSelected),\r
-                                    true);\r
+                                    false);\r
     }\r
     @endcode\r
 \r
index 8e83749c10ea8b99af8ab3a258f36b1609fececf..073feb9ed0f7b9dbf8fcd8022177ef7498d66453 100644 (file)
@@ -31,12 +31,11 @@ Image juce_createIconForFile (const File& file);
 \r
 //==============================================================================\r
 FileListComponent::FileListComponent (DirectoryContentsList& listToShow)\r
-    : ListBox ({}, nullptr),\r
+    : ListBox ({}, this),\r
       DirectoryContentsDisplayComponent (listToShow),\r
       lastDirectory (listToShow.getDirectory())\r
 {\r
     setTitle ("Files");\r
-    setModel (this);\r
     directoryContentsList.addChangeListener (this);\r
 }\r
 \r
@@ -67,14 +66,18 @@ void FileListComponent::scrollToTop()
 \r
 void FileListComponent::setSelectedFile (const File& f)\r
 {\r
-    for (int i = directoryContentsList.getNumFiles(); --i >= 0;)\r
+    if (! directoryContentsList.isStillLoading())\r
     {\r
-        if (directoryContentsList.getFile (i) == f)\r
+        for (int i = directoryContentsList.getNumFiles(); --i >= 0;)\r
         {\r
-            fileWaitingToBeSelected = File();\r
+            if (directoryContentsList.getFile (i) == f)\r
+            {\r
+                fileWaitingToBeSelected = File();\r
 \r
-            selectRow (i);\r
-            return;\r
+                updateContent();\r
+                selectRow (i);\r
+                return;\r
+            }\r
         }\r
     }\r
 \r
index b5bfe529a167e2a729866ab3bc316b3b839bdca7..3d99e92c932f09d5f60b79709f0fa02ee5e70031 100644 (file)
@@ -40,9 +40,9 @@ namespace juce
 \r
     @tags{GUI}\r
 */\r
-class JUCE_API  FileListComponent  : public ListBox,\r
+class JUCE_API  FileListComponent  : private ListBoxModel,\r
+                                     public ListBox,\r
                                      public DirectoryContentsDisplayComponent,\r
-                                     private ListBoxModel,\r
                                      private ChangeListener\r
 {\r
 public:\r
index f5f1e6438cb100d46c0464a37492a34004713df8..916193cfd729fb3e7a66204a86e838421fcd66ca 100644 (file)
@@ -117,39 +117,30 @@ public:
         newList->addChangeListener (this);\r
     }\r
 \r
-    bool selectFile (const File& target)\r
+    void selectFile (const File& target)\r
     {\r
         if (file == target)\r
         {\r
             setSelected (true, true);\r
-            return true;\r
+            return;\r
         }\r
 \r
-        if (target.isAChildOf (file))\r
+        if (subContentsList != nullptr && subContentsList->isStillLoading())\r
         {\r
-            setOpen (true);\r
+            pendingFileSelection.emplace (*this, target);\r
+            return;\r
+        }\r
 \r
-            for (int maxRetries = 500; --maxRetries > 0;)\r
-            {\r
-                for (int i = 0; i < getNumSubItems(); ++i)\r
-                    if (auto* f = dynamic_cast<FileListTreeItem*> (getSubItem (i)))\r
-                        if (f->selectFile (target))\r
-                            return true;\r
+        pendingFileSelection.reset();\r
 \r
-                // if we've just opened and the contents are still loading, wait for it..\r
-                if (subContentsList != nullptr && subContentsList->isStillLoading())\r
-                {\r
-                    Thread::sleep (10);\r
-                    rebuildItemsFromContentList();\r
-                }\r
-                else\r
-                {\r
-                    break;\r
-                }\r
-            }\r
-        }\r
+        if (! target.isAChildOf (file))\r
+            return;\r
 \r
-        return false;\r
+        setOpen (true);\r
+\r
+        for (int i = 0; i < getNumSubItems(); ++i)\r
+            if (auto* f = dynamic_cast<FileListTreeItem*> (getSubItem (i)))\r
+                f->selectFile (target);\r
     }\r
 \r
     void changeListenerCallback (ChangeBroadcaster*) override\r
@@ -224,6 +215,33 @@ public:
     const File file;\r
 \r
 private:\r
+    class PendingFileSelection   : private Timer\r
+    {\r
+    public:\r
+        PendingFileSelection (FileListTreeItem& item, const File& f)\r
+            : owner (item), fileToSelect (f)\r
+        {\r
+            startTimer (10);\r
+        }\r
+\r
+        ~PendingFileSelection() override\r
+        {\r
+            stopTimer();\r
+        }\r
+\r
+    private:\r
+        void timerCallback() override\r
+        {\r
+            // Take a copy of the file here, in case this PendingFileSelection\r
+            // object is destroyed during the call to selectFile.\r
+            owner.selectFile (File { fileToSelect });\r
+        }\r
+\r
+        FileListTreeItem& owner;\r
+        File fileToSelect;\r
+    };\r
+\r
+    Optional<PendingFileSelection> pendingFileSelection;\r
     FileTreeComponent& owner;\r
     DirectoryContentsList* parentContentsList;\r
     int indexInContentsList;\r
@@ -316,8 +334,7 @@ void FileTreeComponent::setDragAndDropDescription (const String& description)
 void FileTreeComponent::setSelectedFile (const File& target)\r
 {\r
     if (auto* t = dynamic_cast<FileListTreeItem*> (getRootItem()))\r
-        if (! t->selectFile (target))\r
-            clearSelectedItems();\r
+        t->selectFile (target);\r
 }\r
 \r
 void FileTreeComponent::setItemHeight (int newHeight)\r
index 50553e409eb1e9e6e04ad156476bbb165d040c21..daa711279fa078fbeaf354af36a3ef96f6c8c0c4 100644 (file)
  #include <vfw.h>\r
  #include <commdlg.h>\r
  #include <commctrl.h>\r
- #include <UIAutomation.h>\r
  #include <sapi.h>\r
- #include <Dxgi.h>\r
+ #include <dxgi.h>\r
+\r
+ #if JUCE_MINGW\r
+  // Some MinGW headers use 'new' as a parameter name\r
+  JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wkeyword-macro")\r
+  #define new new_\r
+  JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+ #endif\r
+\r
+ #include <uiautomation.h>\r
+\r
+ #undef new\r
 \r
  #if JUCE_WEB_BROWSER\r
   #include <exdisp.h>\r
@@ -253,6 +263,7 @@ namespace juce
 #include "windows/juce_ThreadWithProgressWindow.cpp"\r
 #include "windows/juce_TooltipWindow.cpp"\r
 #include "windows/juce_TopLevelWindow.cpp"\r
+#include "windows/juce_VBlankAttachement.cpp"\r
 #include "commands/juce_ApplicationCommandInfo.cpp"\r
 #include "commands/juce_ApplicationCommandManager.cpp"\r
 #include "commands/juce_ApplicationCommandTarget.cpp"\r
@@ -290,6 +301,7 @@ namespace juce
 \r
  #else\r
   #include "native/accessibility/juce_mac_Accessibility.mm"\r
+  #include "native/juce_mac_PerScreenDisplayLinks.h"\r
   #include "native/juce_mac_NSViewComponentPeer.mm"\r
   #include "native/juce_mac_Windowing.mm"\r
   #include "native/juce_mac_MainMenu.mm"\r
@@ -316,6 +328,7 @@ namespace juce
 \r
  JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wzero-as-null-pointer-constant")\r
 \r
+ #include "native/x11/juce_linux_ScopedWindowAssociation.h"\r
  #include "native/juce_linux_Windowing.cpp"\r
  #include "native/x11/juce_linux_XWindowSystem.cpp"\r
 \r
@@ -324,6 +337,28 @@ namespace juce
  #include "native/juce_linux_FileChooser.cpp"\r
 \r
 #elif JUCE_ANDROID\r
+\r
+namespace juce\r
+{\r
+static jobject makeAndroidRect (Rectangle<int> r)\r
+{\r
+    return getEnv()->NewObject (AndroidRect,\r
+                                AndroidRect.constructor,\r
+                                r.getX(),\r
+                                r.getY(),\r
+                                r.getRight(),\r
+                                r.getBottom());\r
+}\r
+\r
+static jobject makeAndroidPoint (Point<int> p)\r
+{\r
+    return getEnv()->NewObject (AndroidPoint,\r
+                                AndroidPoint.create,\r
+                                p.getX(),\r
+                                p.getY());\r
+}\r
+} // namespace juce\r
+\r
  #include "juce_core/files/juce_common_MimeTypes.h"\r
  #include "native/accessibility/juce_android_Accessibility.cpp"\r
  #include "native/juce_android_Windowing.cpp"\r
index ff32e26ff18e145dc3f79f4e6828cbb9d6dbbf22..bd29a18245fb038fff65061e841b9dba8db70e65 100644 (file)
 \r
   ID:                 juce_gui_basics\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE GUI core classes\r
   description:        Basic user-interface components and related classes.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_graphics juce_data_structures\r
   OSXFrameworks:      Cocoa QuartzCore\r
@@ -278,6 +278,7 @@ namespace juce
 #include "windows/juce_NativeMessageBox.h"\r
 #include "windows/juce_ThreadWithProgressWindow.h"\r
 #include "windows/juce_TooltipWindow.h"\r
+#include "windows/juce_VBlankAttachement.h"\r
 #include "layout/juce_MultiDocumentPanel.h"\r
 #include "layout/juce_SidePanel.h"\r
 #include "filebrowser/juce_FileBrowserListener.h"\r
index da33a7ea9b71a6fef68e4529e50bf53ca16664b8..40fea0a161bb4945247b36ae589c8574a02924d7 100644 (file)
@@ -31,7 +31,7 @@ namespace juce
     Receives callbacks when keys are pressed.\r
 \r
     You can add a key listener to a component to be informed when that component\r
-    gets key events. See the Component::addListener method for more details.\r
+    gets key events. See the Component::addKeyListener method for more details.\r
 \r
     @see KeyPress, Component::addKeyListener, KeyPressMappingSet\r
 \r
index 5270459e4036d3f90e40caff8536b5b805cafb0e..dcf999e9288eaffab91f5ad18047f4b8021ee3fb 100644 (file)
@@ -163,10 +163,10 @@ public:
 \r
     //==============================================================================\r
     /** Returns a copy of only the mouse-button flags */\r
-    JUCE_NODISCARD ModifierKeys withOnlyMouseButtons() const noexcept                  { return ModifierKeys (flags & allMouseButtonModifiers); }\r
+    [[nodiscard]] ModifierKeys withOnlyMouseButtons() const noexcept                  { return ModifierKeys (flags & allMouseButtonModifiers); }\r
 \r
     /** Returns a copy of only the non-mouse flags */\r
-    JUCE_NODISCARD ModifierKeys withoutMouseButtons() const noexcept                   { return ModifierKeys (flags & ~allMouseButtonModifiers); }\r
+    [[nodiscard]] ModifierKeys withoutMouseButtons() const noexcept                   { return ModifierKeys (flags & ~allMouseButtonModifiers); }\r
 \r
     bool operator== (const ModifierKeys other) const noexcept                          { return flags == other.flags; }\r
     bool operator!= (const ModifierKeys other) const noexcept                          { return flags != other.flags; }\r
@@ -175,8 +175,8 @@ public:
     /** Returns the raw flags for direct testing. */\r
     inline int getRawFlags() const noexcept                                            { return flags; }\r
 \r
-    JUCE_NODISCARD ModifierKeys withoutFlags (int rawFlagsToClear) const noexcept      { return ModifierKeys (flags & ~rawFlagsToClear); }\r
-    JUCE_NODISCARD ModifierKeys withFlags (int rawFlagsToSet) const noexcept           { return ModifierKeys (flags | rawFlagsToSet); }\r
+    [[nodiscard]] ModifierKeys withoutFlags (int rawFlagsToClear) const noexcept      { return ModifierKeys (flags & ~rawFlagsToClear); }\r
+    [[nodiscard]] ModifierKeys withFlags (int rawFlagsToSet) const noexcept           { return ModifierKeys (flags | rawFlagsToSet); }\r
 \r
     /** Tests a combination of flags and returns true if any of them are set. */\r
     bool testFlags (int flagsToTest) const noexcept                                    { return (flags & flagsToTest) != 0; }\r
index b255a2a0f0381871c73fb01174974d153339bfb9..fe5ac1a3003020913227343addcbe474e7e9a1c3 100644 (file)
@@ -26,7 +26,6 @@
 namespace juce\r
 {\r
 \r
-//==============================================================================\r
 /**\r
     An abstract base class which can be implemented by components that function as\r
     text editors.\r
@@ -108,7 +107,8 @@ public:
         decimalKeyboard,\r
         urlKeyboard,\r
         emailAddressKeyboard,\r
-        phoneNumberKeyboard\r
+        phoneNumberKeyboard,\r
+        passwordKeyboard\r
     };\r
 \r
     /** Returns the target's preference for the type of keyboard that would be most appropriate.\r
index aa143a3506223b08ec156240b496eadc5268a66c..b012520d5f24937aaf11a2972a37434bcaf264d2 100644 (file)
@@ -1047,7 +1047,7 @@ void Grid::performLayout (Rectangle<int> targetArea)
                                 + targetArea.toFloat().getPosition();\r
 \r
         if (auto* c = item->associatedComponent)\r
-            c->setBounds (item->currentBounds.toNearestIntEdges());\r
+            c->setBounds (item->currentBounds.getSmallestIntegerContainer());\r
     }\r
 }\r
 \r
index 758b5d96ae66f60c3969f7cadb6036866041c085..dfd36a45c979eb9a8c2f93978233617e4b591769 100644 (file)
@@ -159,7 +159,8 @@ void SidePanel::paint (Graphics& g)
                                                                                 : shadowArea.getTopLeft()).toFloat(), false));\r
     g.fillRect (shadowArea);\r
 \r
-    g.excludeClipRegion (shadowArea);\r
+    g.reduceClipRegion (getLocalBounds().withTrimmedRight (shadowArea.getWidth())\r
+                                        .withX (isOnLeft ? 0 : shadowArea.getWidth()));\r
     g.fillAll (bgColour);\r
 }\r
 \r
@@ -242,10 +243,8 @@ void SidePanel::lookAndFeelChanged()
     titleLabel.setJustificationType (lf.getSidePanelTitleJustification (*this));\r
 }\r
 \r
-void SidePanel::componentMovedOrResized (Component& component, bool wasMoved, bool wasResized)\r
+void SidePanel::componentMovedOrResized (Component& component, [[maybe_unused]] bool wasMoved, bool wasResized)\r
 {\r
-    ignoreUnused (wasMoved);\r
-\r
     if (wasResized && (&component == parent))\r
         setBounds (calculateBoundsInParent (component));\r
 }\r
index 0ec5d7d253a35b4d239d970e95aaafcb8d0440ac..3c6a6e66fda6072b125b456aaeb7cf938b465bbd 100644 (file)
@@ -464,10 +464,9 @@ void LookAndFeel_V3::drawLinearSliderBackground (Graphics& g, int x, int y, int
     g.strokePath (indent, PathStrokeType (0.5f));\r
 }\r
 \r
-void LookAndFeel_V3::drawPopupMenuBackground (Graphics& g, int width, int height)\r
+void LookAndFeel_V3::drawPopupMenuBackground (Graphics& g, [[maybe_unused]] int width, [[maybe_unused]] int height)\r
 {\r
     g.fillAll (findColour (PopupMenu::backgroundColourId));\r
-    ignoreUnused (width, height);\r
 \r
    #if ! JUCE_MAC\r
     g.setColour (findColour (PopupMenu::textColourId).withAlpha (0.6f));\r
index bd87b26a968886241ad3e08407433814be7890db..d400073ad6502b6cf19d9913af85da5154e2f2fc 100644 (file)
@@ -353,12 +353,10 @@ void LookAndFeel_V4::drawToggleButton (Graphics& g, ToggleButton& button,
 void LookAndFeel_V4::drawTickBox (Graphics& g, Component& component,\r
                                   float x, float y, float w, float h,\r
                                   const bool ticked,\r
-                                  const bool isEnabled,\r
-                                  const bool shouldDrawButtonAsHighlighted,\r
-                                  const bool shouldDrawButtonAsDown)\r
+                                  [[maybe_unused]] const bool isEnabled,\r
+                                  [[maybe_unused]] const bool shouldDrawButtonAsHighlighted,\r
+                                  [[maybe_unused]] const bool shouldDrawButtonAsDown)\r
 {\r
-    ignoreUnused (isEnabled, shouldDrawButtonAsHighlighted, shouldDrawButtonAsDown);\r
-\r
     Rectangle<float> tickBounds (x, y, w, h);\r
 \r
     g.setColour (component.findColour (ToggleButton::tickDisabledColourId));\r
@@ -619,10 +617,8 @@ int LookAndFeel_V4::getDefaultScrollbarWidth()
 }\r
 \r
 void LookAndFeel_V4::drawScrollbar (Graphics& g, ScrollBar& scrollbar, int x, int y, int width, int height,\r
-                                    bool isScrollbarVertical, int thumbStartPosition, int thumbSize, bool isMouseOver, bool isMouseDown)\r
+                                    bool isScrollbarVertical, int thumbStartPosition, int thumbSize, bool isMouseOver, [[maybe_unused]] bool isMouseDown)\r
 {\r
-    ignoreUnused (isMouseDown);\r
-\r
     Rectangle<int> thumbBounds;\r
 \r
     if (isScrollbarVertical)\r
@@ -1253,10 +1249,8 @@ void LookAndFeel_V4::drawPropertyComponentBackground (Graphics& g, int width, in
     g.fillRect  (0, 0, width, height - 1);\r
 }\r
 \r
-void LookAndFeel_V4::drawPropertyComponentLabel (Graphics& g, int width, int height, PropertyComponent& component)\r
+void LookAndFeel_V4::drawPropertyComponentLabel (Graphics& g, [[maybe_unused]] int width, int height, PropertyComponent& component)\r
 {\r
-    ignoreUnused (width);\r
-\r
     auto indent = getPropertyComponentIndent (component);\r
 \r
     g.setColour (component.findColour (PropertyComponent::labelTextColourId)\r
index ef413750dab14ef35966aa899af98628f92e303a..8dd135733a6c292656737fea3ffffb7b842a465b 100644 (file)
@@ -324,12 +324,16 @@ private:
 //==============================================================================\r
 struct MenuWindow  : public Component\r
 {\r
-    MenuWindow (const PopupMenu& menu, MenuWindow* parentWindow,\r
-                Options opts, bool alignToRectangle, bool shouldDismissOnMouseUp,\r
-                ApplicationCommandManager** manager, float parentScaleFactor = 1.0f)\r
+    MenuWindow (const PopupMenu& menu,\r
+                MenuWindow* parentWindow,\r
+                Options opts,\r
+                bool alignToRectangle,\r
+                bool shouldDismissOnMouseUp,\r
+                ApplicationCommandManager** manager,\r
+                float parentScaleFactor = 1.0f)\r
         : Component ("menu"),\r
           parent (parentWindow),\r
-          options (opts.withParentComponent (getLookAndFeel().getParentComponentForMenuOptions (opts))),\r
+          options (opts.withParentComponent (findLookAndFeel (menu, parentWindow)->getParentComponentForMenuOptions (opts))),\r
           managerOfChosenCommand (manager),\r
           componentAttachedTo (options.getTargetComponent()),\r
           dismissOnMouseUp (shouldDismissOnMouseUp),\r
@@ -343,8 +347,7 @@ struct MenuWindow  : public Component
         setAlwaysOnTop (true);\r
         setFocusContainerType (FocusContainerType::focusContainer);\r
 \r
-        setLookAndFeel (parent != nullptr ? &(parent->getLookAndFeel())\r
-                                          : menu.lookAndFeel.get());\r
+        setLookAndFeel (findLookAndFeel (menu, parentWindow));\r
 \r
         auto& lf = getLookAndFeel();\r
 \r
@@ -1291,6 +1294,17 @@ struct MenuWindow  : public Component
                                                        }));\r
     }\r
 \r
+    LookAndFeel* findLookAndFeel (const PopupMenu& menu, MenuWindow* parentWindow) const\r
+    {\r
+        if (parentWindow != nullptr)\r
+            return &(parentWindow->getLookAndFeel());\r
+\r
+        if (auto* lnf = menu.lookAndFeel.get())\r
+            return lnf;\r
+\r
+        return &getLookAndFeel();\r
+    }\r
+\r
     //==============================================================================\r
     MenuWindow* parent;\r
     const Options options;\r
@@ -2098,7 +2112,7 @@ struct PopupMenuCompletionCallback  : public ModalComponentManager::Callback
 \r
 int PopupMenu::showWithOptionalCallback (const Options& options,\r
                                          ModalComponentManager::Callback* userCallback,\r
-                                         bool canBeModal)\r
+                                         [[maybe_unused]] bool canBeModal)\r
 {\r
     std::unique_ptr<ModalComponentManager::Callback> userCallbackDeleter (userCallback);\r
     std::unique_ptr<PopupMenuCompletionCallback> callback (new PopupMenuCompletionCallback());\r
@@ -2120,7 +2134,6 @@ int PopupMenu::showWithOptionalCallback (const Options& options,
         if (userCallback == nullptr && canBeModal)\r
             return window->runModalLoop();\r
        #else\r
-        ignoreUnused (canBeModal);\r
         jassert (! (userCallback == nullptr && canBeModal));\r
        #endif\r
     }\r
index be05c9af26e019e437db9207ca666f73ebe56596..6ca8c721d72d80e6cc528a5cce3a108fb677422d 100644 (file)
@@ -483,8 +483,8 @@ public:
 \r
             @see withTargetComponent, withTargetScreenArea\r
         */\r
-        JUCE_NODISCARD Options withTargetComponent (Component* targetComponent) const;\r
-        JUCE_NODISCARD Options withTargetComponent (Component& targetComponent) const;\r
+        [[nodiscard]] Options withTargetComponent (Component* targetComponent) const;\r
+        [[nodiscard]] Options withTargetComponent (Component& targetComponent) const;\r
 \r
         /** Sets the region of the screen next to which the menu should be displayed.\r
 \r
@@ -500,7 +500,7 @@ public:
 \r
             @see withMousePosition\r
         */\r
-        JUCE_NODISCARD Options withTargetScreenArea (Rectangle<int> targetArea) const;\r
+        [[nodiscard]] Options withTargetScreenArea (Rectangle<int> targetArea) const;\r
 \r
         /** Sets the target screen area to match the current mouse position.\r
 \r
@@ -508,7 +508,7 @@ public:
 \r
             @see withTargetScreenArea\r
         */\r
-        JUCE_NODISCARD Options withMousePosition() const;\r
+        [[nodiscard]] Options withMousePosition() const;\r
 \r
         /** If the passed component has been deleted when the popup menu exits,\r
             the selected item's action will not be called.\r
@@ -517,26 +517,26 @@ public:
             callback, in the case that the callback needs to access a component that\r
             may be deleted.\r
         */\r
-        JUCE_NODISCARD Options withDeletionCheck (Component& componentToWatchForDeletion) const;\r
+        [[nodiscard]] Options withDeletionCheck (Component& componentToWatchForDeletion) const;\r
 \r
         /** Sets the minimum width of the popup window. */\r
-        JUCE_NODISCARD Options withMinimumWidth (int minWidth) const;\r
+        [[nodiscard]] Options withMinimumWidth (int minWidth) const;\r
 \r
         /** Sets the minimum number of columns in the popup window. */\r
-        JUCE_NODISCARD Options withMinimumNumColumns (int minNumColumns) const;\r
+        [[nodiscard]] Options withMinimumNumColumns (int minNumColumns) const;\r
 \r
         /** Sets the maximum number of columns in the popup window. */\r
-        JUCE_NODISCARD Options withMaximumNumColumns (int maxNumColumns) const;\r
+        [[nodiscard]] Options withMaximumNumColumns (int maxNumColumns) const;\r
 \r
         /** Sets the default height of each item in the popup menu. */\r
-        JUCE_NODISCARD Options withStandardItemHeight (int standardHeight) const;\r
+        [[nodiscard]] Options withStandardItemHeight (int standardHeight) const;\r
 \r
         /** Sets an item which must be visible when the menu is initially drawn.\r
 \r
             This is useful to ensure that a particular item is shown when the menu\r
             contains too many items to display on a single screen.\r
         */\r
-        JUCE_NODISCARD Options withItemThatMustBeVisible (int idOfItemToBeVisible) const;\r
+        [[nodiscard]] Options withItemThatMustBeVisible (int idOfItemToBeVisible) const;\r
 \r
         /** Sets a component that the popup menu will be drawn into.\r
 \r
@@ -547,10 +547,10 @@ public:
             avoid this unwanted behaviour, but with the downside that the menu size\r
             will be constrained by the size of the parent component.\r
         */\r
-        JUCE_NODISCARD Options withParentComponent (Component* parentComponent) const;\r
+        [[nodiscard]] Options withParentComponent (Component* parentComponent) const;\r
 \r
         /** Sets the direction of the popup menu relative to the target screen area. */\r
-        JUCE_NODISCARD Options withPreferredPopupDirection (PopupDirection direction) const;\r
+        [[nodiscard]] Options withPreferredPopupDirection (PopupDirection direction) const;\r
 \r
         /** Sets an item to select in the menu.\r
 \r
@@ -560,7 +560,7 @@ public:
             than needing to move the highlighted row down from the top of the menu each time\r
             it is opened.\r
         */\r
-        JUCE_NODISCARD Options withInitiallySelectedItem (int idOfItemToBeSelected) const;\r
+        [[nodiscard]] Options withInitiallySelectedItem (int idOfItemToBeSelected) const;\r
 \r
         //==============================================================================\r
         /** Gets the parent component. This may be nullptr if the Component has been deleted.\r
index c36306d2fef220b0b0013e84a1cd0f7f784ea64f..9b60308b4e2440011c4cff3814fad78771a8ee4f 100644 (file)
@@ -62,10 +62,8 @@ static Rectangle<float> getLogoArea (Rectangle<float> parentRect)
 }\r
 \r
 //==============================================================================\r
-JUCESplashScreen::JUCESplashScreen (Component& parent)\r
+JUCESplashScreen::JUCESplashScreen ([[maybe_unused]] Component& parent)\r
 {\r
-    ignoreUnused (parent);\r
-\r
    #if JUCE_DISPLAY_SPLASH_SCREEN\r
     if (splashDisplayTime == 0\r
          || Time::getMillisecondCounter() < splashDisplayTime + (uint32) millisecondsToDisplaySplash)\r
index 24d0e63a042ab71649f87606c0912a28eca2b0b4..646cdd1932a446e3d34120b6a4ed04262b113d4c 100644 (file)
@@ -57,18 +57,18 @@ public:
         return lastPeer;\r
     }\r
 \r
-    Component* findComponentAt (Point<float> screenPos)\r
+    static Component* findComponentAt (Point<float> screenPos, ComponentPeer* peer)\r
     {\r
-        if (auto* peer = getPeer())\r
-        {\r
-            auto relativePos = ScalingHelpers::unscaledScreenPosToScaled (peer->getComponent(),\r
-                                                                          peer->globalToLocal (screenPos));\r
-            auto& comp = peer->getComponent();\r
+        if (! ComponentPeer::isValidPeer (peer))\r
+            return nullptr;\r
 \r
-            // (the contains() call is needed to test for overlapping desktop windows)\r
-            if (comp.contains (relativePos))\r
-                return comp.getComponentAt (relativePos);\r
-        }\r
+        auto relativePos = ScalingHelpers::unscaledScreenPosToScaled (peer->getComponent(),\r
+                                                                      peer->globalToLocal (screenPos));\r
+        auto& comp = peer->getComponent();\r
+\r
+        // (the contains() call is needed to test for overlapping desktop windows)\r
+        if (comp.contains (relativePos))\r
+            return comp.getComponentAt (relativePos);\r
 \r
         return nullptr;\r
     }\r
@@ -244,11 +244,12 @@ public:
 \r
     void setPeer (ComponentPeer& newPeer, const PointerState& pointerState, Time time)\r
     {\r
-        if (&newPeer != lastPeer)\r
+        if (&newPeer != lastPeer && (   findComponentAt (pointerState.position, &newPeer) != nullptr\r
+                                     || findComponentAt (pointerState.position, lastPeer) == nullptr))\r
         {\r
             setComponentUnderMouse (nullptr, pointerState, time);\r
             lastPeer = &newPeer;\r
-            setComponentUnderMouse (findComponentAt (pointerState.position), pointerState, time);\r
+            setComponentUnderMouse (findComponentAt (pointerState.position, getPeer()), pointerState, time);\r
         }\r
     }\r
 \r
@@ -257,7 +258,7 @@ public:
         const auto& newScreenPos = newPointerState.position;\r
 \r
         if (! isDragging())\r
-            setComponentUnderMouse (findComponentAt (newScreenPos), newPointerState, time);\r
+            setComponentUnderMouse (findComponentAt (newScreenPos, getPeer()), newPointerState, time);\r
 \r
         if ((newPointerState != lastPointerState) || forceUpdate)\r
         {\r
index 2b516792b2dc98a5b584f3c78d98c13bcfca501e..97fd53bc02a89d646f59937b7ccea41b369450c9 100644 (file)
@@ -41,13 +41,13 @@ public:
     bool operator== (const PointerState& other) const noexcept   { return tie() == other.tie(); }\r
     bool operator!= (const PointerState& other) const noexcept   { return tie() != other.tie(); }\r
 \r
-    JUCE_NODISCARD PointerState withPositionOffset (Point<float> x)        const noexcept { return with (&PointerState::position, position + x); }\r
-    JUCE_NODISCARD PointerState withPosition (Point<float> x)              const noexcept { return with (&PointerState::position, x); }\r
-    JUCE_NODISCARD PointerState withPressure (float x)                     const noexcept { return with (&PointerState::pressure, x); }\r
-    JUCE_NODISCARD PointerState withOrientation (float x)                  const noexcept { return with (&PointerState::orientation, x); }\r
-    JUCE_NODISCARD PointerState withRotation (float x)                     const noexcept { return with (&PointerState::rotation, x); }\r
-    JUCE_NODISCARD PointerState withTiltX (float x)                        const noexcept { return with (&PointerState::tiltX, x); }\r
-    JUCE_NODISCARD PointerState withTiltY (float x)                        const noexcept { return with (&PointerState::tiltY, x); }\r
+    [[nodiscard]] PointerState withPositionOffset (Point<float> x)        const noexcept { return with (&PointerState::position, position + x); }\r
+    [[nodiscard]] PointerState withPosition (Point<float> x)              const noexcept { return with (&PointerState::position, x); }\r
+    [[nodiscard]] PointerState withPressure (float x)                     const noexcept { return with (&PointerState::pressure, x); }\r
+    [[nodiscard]] PointerState withOrientation (float x)                  const noexcept { return with (&PointerState::orientation, x); }\r
+    [[nodiscard]] PointerState withRotation (float x)                     const noexcept { return with (&PointerState::rotation, x); }\r
+    [[nodiscard]] PointerState withTiltX (float x)                        const noexcept { return with (&PointerState::tiltX, x); }\r
+    [[nodiscard]] PointerState withTiltY (float x)                        const noexcept { return with (&PointerState::tiltY, x); }\r
 \r
     Point<float> position;\r
     float pressure    = MouseInputSource::defaultPressure;\r
index a0976b455515149f22d7017fbec7ebbab32253ae..0eba1c6365854bf974b613e8e0e9a1c4701ebc06 100644 (file)
@@ -58,6 +58,7 @@ public:
     as a base class and calling setTooltip().\r
 \r
     Many of the JUCE widgets already use this as a base class to implement their\r
+    tooltips. See the TooltipWindow docs for more information about implementing\r
     tooltips.\r
 \r
     @see TooltipClient, TooltipWindow\r
index 1ac5ed6705b2eb5d0a19207eb821fdda7fced30d..b6b2dee71cbc7c02bae2c9e37929d6e596adcc36 100644 (file)
@@ -297,21 +297,13 @@ public:
         {\r
             const auto scale = Desktop::getInstance().getDisplays().getPrimaryDisplay()->scale;\r
 \r
-            const auto screenBounds = accessibilityHandler.getComponent().getScreenBounds() * scale;\r
+            LocalRef<jobject> screenBounds (makeAndroidRect (accessibilityHandler.getComponent().getScreenBounds() * scale));\r
 \r
-            LocalRef<jobject> rect (env->NewObject (AndroidRect, AndroidRect.constructor,\r
-                                                    screenBounds.getX(),     screenBounds.getY(),\r
-                                                    screenBounds.getRight(), screenBounds.getBottom()));\r
+            env->CallVoidMethod (info, AndroidAccessibilityNodeInfo.setBoundsInScreen, screenBounds.get());\r
 \r
-            env->CallVoidMethod (info, AndroidAccessibilityNodeInfo.setBoundsInScreen, rect.get());\r
+            LocalRef<jobject> boundsInParent (makeAndroidRect (accessibilityHandler.getComponent().getBoundsInParent() * scale));\r
 \r
-            const auto boundsInParent = accessibilityHandler.getComponent().getBoundsInParent() * scale;\r
-\r
-            rect = LocalRef<jobject> (env->NewObject (AndroidRect, AndroidRect.constructor,\r
-                                                      boundsInParent.getX(),     boundsInParent.getY(),\r
-                                                      boundsInParent.getRight(), boundsInParent.getBottom()));\r
-\r
-            env->CallVoidMethod (info, AndroidAccessibilityNodeInfo.setBoundsInParent, rect.get());\r
+            env->CallVoidMethod (info, AndroidAccessibilityNodeInfo.setBoundsInParent, boundsInParent.get());\r
         }\r
 \r
         const auto state = accessibilityHandler.getCurrentState();\r
index 5874ad3e0bcc6d3a5d277f7cf462f196b5445821..e7f8516cb1b27cce797520424e5d02e5a7c45da5 100644 (file)
@@ -217,7 +217,7 @@ private:
         template <typename Func, typename... Items>\r
         static constexpr void forEach (Func&& func, Items&&... items)\r
         {\r
-            (void) std::initializer_list<int> { ((void) func (std::forward<Items> (items)), 0)... };\r
+            (func (std::forward<Items> (items)), ...);\r
         }\r
 \r
     public:\r
index 9be3ac5e3556318e856bb6f195571921a8fe0ee7..01d383c03d307b4c3590799f133d090064684d52 100644 (file)
@@ -155,11 +155,13 @@ void sendAccessibilityPropertyChangedEvent (const AccessibilityHandler& handler,
 \r
 void notifyAccessibilityEventInternal (const AccessibilityHandler& handler, InternalAccessibilityEvent eventType)\r
 {\r
+    using namespace ComTypes::Constants;\r
+\r
     if (eventType == InternalAccessibilityEvent::elementCreated\r
         || eventType == InternalAccessibilityEvent::elementDestroyed)\r
     {\r
         if (auto* parent = handler.getParent())\r
-            sendAccessibilityAutomationEvent (*parent, ComTypes::UIA_LayoutInvalidatedEventId);\r
+            sendAccessibilityAutomationEvent (*parent, UIA_LayoutInvalidatedEventId);\r
 \r
         return;\r
     }\r
@@ -176,9 +178,9 @@ void notifyAccessibilityEventInternal (const AccessibilityHandler& handler, Inte
     {\r
         switch (eventType)\r
         {\r
-            case InternalAccessibilityEvent::focusChanged:           return ComTypes::UIA_AutomationFocusChangedEventId;\r
-            case InternalAccessibilityEvent::windowOpened:           return ComTypes::UIA_Window_WindowOpenedEventId;\r
-            case InternalAccessibilityEvent::windowClosed:           return ComTypes::UIA_Window_WindowClosedEventId;\r
+            case InternalAccessibilityEvent::focusChanged:           return UIA_AutomationFocusChangedEventId;\r
+            case InternalAccessibilityEvent::windowOpened:           return UIA_Window_WindowOpenedEventId;\r
+            case InternalAccessibilityEvent::windowClosed:           return UIA_Window_WindowClosedEventId;\r
             case InternalAccessibilityEvent::elementCreated:\r
             case InternalAccessibilityEvent::elementDestroyed:\r
             case InternalAccessibilityEvent::elementMovedOrResized:  break;\r
@@ -221,12 +223,14 @@ void AccessibilityHandler::notifyAccessibilityEvent (AccessibilityEvent eventTyp
 \r
     auto event = [eventType]() -> EVENTID\r
     {\r
+        using namespace ComTypes::Constants;\r
+\r
         switch (eventType)\r
         {\r
-            case AccessibilityEvent::textSelectionChanged:  return ComTypes::UIA_Text_TextSelectionChangedEventId;\r
-            case AccessibilityEvent::textChanged:           return ComTypes::UIA_Text_TextChangedEventId;\r
-            case AccessibilityEvent::structureChanged:      return ComTypes::UIA_StructureChangedEventId;\r
-            case AccessibilityEvent::rowSelectionChanged:   return ComTypes::UIA_SelectionItem_ElementSelectedEventId;\r
+            case AccessibilityEvent::textSelectionChanged:  return UIA_Text_TextSelectionChangedEventId;\r
+            case AccessibilityEvent::textChanged:           return UIA_Text_TextChangedEventId;\r
+            case AccessibilityEvent::structureChanged:      return UIA_StructureChangedEventId;\r
+            case AccessibilityEvent::rowSelectionChanged:   return UIA_SelectionItem_ElementSelectedEventId;\r
             case AccessibilityEvent::titleChanged:\r
             case AccessibilityEvent::valueChanged:          break;\r
         }\r
index d7712203dc636ec0bf192a1b62c56786d2bd8491..8b13c317db3524c3ec62ad8d2689d6d07aefe1a4 100644 (file)
@@ -96,46 +96,48 @@ static String getAutomationId (const AccessibilityHandler& handler)
 \r
 static auto roleToControlTypeId (AccessibilityRole roleType)\r
 {\r
+    using namespace ComTypes::Constants;\r
+\r
     switch (roleType)\r
     {\r
         case AccessibilityRole::popupMenu:\r
         case AccessibilityRole::dialogWindow:\r
         case AccessibilityRole::splashScreen:\r
-        case AccessibilityRole::window:        return ComTypes::UIA_WindowControlTypeId;\r
+        case AccessibilityRole::window:        return UIA_WindowControlTypeId;\r
 \r
         case AccessibilityRole::label:\r
-        case AccessibilityRole::staticText:    return ComTypes::UIA_TextControlTypeId;\r
+        case AccessibilityRole::staticText:    return UIA_TextControlTypeId;\r
 \r
         case AccessibilityRole::column:\r
-        case AccessibilityRole::row:           return ComTypes::UIA_ListItemControlTypeId;\r
-\r
-        case AccessibilityRole::button:        return ComTypes::UIA_ButtonControlTypeId;\r
-        case AccessibilityRole::toggleButton:  return ComTypes::UIA_CheckBoxControlTypeId;\r
-        case AccessibilityRole::radioButton:   return ComTypes::UIA_RadioButtonControlTypeId;\r
-        case AccessibilityRole::comboBox:      return ComTypes::UIA_ComboBoxControlTypeId;\r
-        case AccessibilityRole::image:         return ComTypes::UIA_ImageControlTypeId;\r
-        case AccessibilityRole::slider:        return ComTypes::UIA_SliderControlTypeId;\r
-        case AccessibilityRole::editableText:  return ComTypes::UIA_EditControlTypeId;\r
-        case AccessibilityRole::menuItem:      return ComTypes::UIA_MenuItemControlTypeId;\r
-        case AccessibilityRole::menuBar:       return ComTypes::UIA_MenuBarControlTypeId;\r
-        case AccessibilityRole::table:         return ComTypes::UIA_TableControlTypeId;\r
-        case AccessibilityRole::tableHeader:   return ComTypes::UIA_HeaderControlTypeId;\r
-        case AccessibilityRole::cell:          return ComTypes::UIA_DataItemControlTypeId;\r
-        case AccessibilityRole::hyperlink:     return ComTypes::UIA_HyperlinkControlTypeId;\r
-        case AccessibilityRole::list:          return ComTypes::UIA_ListControlTypeId;\r
-        case AccessibilityRole::listItem:      return ComTypes::UIA_ListItemControlTypeId;\r
-        case AccessibilityRole::tree:          return ComTypes::UIA_TreeControlTypeId;\r
-        case AccessibilityRole::treeItem:      return ComTypes::UIA_TreeItemControlTypeId;\r
-        case AccessibilityRole::progressBar:   return ComTypes::UIA_ProgressBarControlTypeId;\r
-        case AccessibilityRole::group:         return ComTypes::UIA_GroupControlTypeId;\r
-        case AccessibilityRole::scrollBar:     return ComTypes::UIA_ScrollBarControlTypeId;\r
-        case AccessibilityRole::tooltip:       return ComTypes::UIA_ToolTipControlTypeId;\r
+        case AccessibilityRole::row:           return UIA_ListItemControlTypeId;\r
+\r
+        case AccessibilityRole::button:        return UIA_ButtonControlTypeId;\r
+        case AccessibilityRole::toggleButton:  return UIA_CheckBoxControlTypeId;\r
+        case AccessibilityRole::radioButton:   return UIA_RadioButtonControlTypeId;\r
+        case AccessibilityRole::comboBox:      return UIA_ComboBoxControlTypeId;\r
+        case AccessibilityRole::image:         return UIA_ImageControlTypeId;\r
+        case AccessibilityRole::slider:        return UIA_SliderControlTypeId;\r
+        case AccessibilityRole::editableText:  return UIA_EditControlTypeId;\r
+        case AccessibilityRole::menuItem:      return UIA_MenuItemControlTypeId;\r
+        case AccessibilityRole::menuBar:       return UIA_MenuBarControlTypeId;\r
+        case AccessibilityRole::table:         return UIA_TableControlTypeId;\r
+        case AccessibilityRole::tableHeader:   return UIA_HeaderControlTypeId;\r
+        case AccessibilityRole::cell:          return UIA_DataItemControlTypeId;\r
+        case AccessibilityRole::hyperlink:     return UIA_HyperlinkControlTypeId;\r
+        case AccessibilityRole::list:          return UIA_ListControlTypeId;\r
+        case AccessibilityRole::listItem:      return UIA_ListItemControlTypeId;\r
+        case AccessibilityRole::tree:          return UIA_TreeControlTypeId;\r
+        case AccessibilityRole::treeItem:      return UIA_TreeItemControlTypeId;\r
+        case AccessibilityRole::progressBar:   return UIA_ProgressBarControlTypeId;\r
+        case AccessibilityRole::group:         return UIA_GroupControlTypeId;\r
+        case AccessibilityRole::scrollBar:     return UIA_ScrollBarControlTypeId;\r
+        case AccessibilityRole::tooltip:       return UIA_ToolTipControlTypeId;\r
 \r
         case AccessibilityRole::ignored:\r
         case AccessibilityRole::unspecified:   break;\r
     };\r
 \r
-    return ComTypes::UIA_CustomControlTypeId;\r
+    return UIA_CustomControlTypeId;\r
 }\r
 \r
 //==============================================================================\r
@@ -206,38 +208,40 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPatternProvider (PATTERNID pId, IUn
                 return false;\r
             };\r
 \r
+            using namespace ComTypes::Constants;\r
+\r
             switch (pId)\r
             {\r
-                case ComTypes::UIA_WindowPatternId:\r
+                case UIA_WindowPatternId:\r
                 {\r
                     if (fragmentRoot)\r
                         return new UIAWindowProvider (this);\r
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_TransformPatternId:\r
+                case UIA_TransformPatternId:\r
                 {\r
                     if (fragmentRoot)\r
                         return new UIATransformProvider (this);\r
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_TextPatternId:\r
-                case ComTypes::UIA_TextPattern2Id:\r
+                case UIA_TextPatternId:\r
+                case UIA_TextPattern2Id:\r
                 {\r
                     if (accessibilityHandler.getTextInterface() != nullptr)\r
                         return new UIATextProvider (this);\r
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_ValuePatternId:\r
+                case UIA_ValuePatternId:\r
                 {\r
                     if (accessibilityHandler.getValueInterface() != nullptr)\r
                         return new UIAValueProvider (this);\r
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_RangeValuePatternId:\r
+                case UIA_RangeValuePatternId:\r
                 {\r
                     if (accessibilityHandler.getValueInterface() != nullptr\r
                         && accessibilityHandler.getValueInterface()->getRange().isValid())\r
@@ -247,7 +251,7 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPatternProvider (PATTERNID pId, IUn
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_TogglePatternId:\r
+                case UIA_TogglePatternId:\r
                 {\r
                     if (accessibilityHandler.getCurrentState().isCheckable()\r
                         && (accessibilityHandler.getActions().contains (AccessibilityActionType::toggle)\r
@@ -258,7 +262,7 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPatternProvider (PATTERNID pId, IUn
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_SelectionPatternId:\r
+                case UIA_SelectionPatternId:\r
                 {\r
                     if (role == AccessibilityRole::list\r
                         || role == AccessibilityRole::popupMenu\r
@@ -269,7 +273,7 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPatternProvider (PATTERNID pId, IUn
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_SelectionItemPatternId:\r
+                case UIA_SelectionItemPatternId:\r
                 {\r
                     auto state = accessibilityHandler.getCurrentState();\r
 \r
@@ -280,31 +284,31 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPatternProvider (PATTERNID pId, IUn
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_TablePatternId:\r
-                case ComTypes::UIA_GridPatternId:\r
+                case UIA_TablePatternId:\r
+                case UIA_GridPatternId:\r
                 {\r
                     if (accessibilityHandler.getTableInterface() != nullptr\r
-                        && (pId == ComTypes::UIA_GridPatternId || accessibilityHandler.getRole() == AccessibilityRole::table))\r
+                        && (pId == UIA_GridPatternId || accessibilityHandler.getRole() == AccessibilityRole::table))\r
                         return static_cast<ComTypes::IGridProvider*> (new UIAGridProvider (this));\r
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_TableItemPatternId:\r
-                case ComTypes::UIA_GridItemPatternId:\r
+                case UIA_TableItemPatternId:\r
+                case UIA_GridItemPatternId:\r
                 {\r
                     if (isListOrTableCell (accessibilityHandler))\r
                         return static_cast<ComTypes::IGridItemProvider*> (new UIAGridItemProvider (this));\r
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_InvokePatternId:\r
+                case UIA_InvokePatternId:\r
                 {\r
                     if (accessibilityHandler.getActions().contains (AccessibilityActionType::press))\r
                         return new UIAInvokeProvider (this);\r
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_ExpandCollapsePatternId:\r
+                case UIA_ExpandCollapsePatternId:\r
                 {\r
                     if (accessibilityHandler.getActions().contains (AccessibilityActionType::showMenu)\r
                         && accessibilityHandler.getCurrentState().isExpandable())\r
@@ -312,14 +316,14 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPatternProvider (PATTERNID pId, IUn
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_ScrollPatternId:\r
+                case UIA_ScrollPatternId:\r
                 {\r
                     if (accessibilityHandler.getTableInterface() != nullptr)\r
                         return new UIAScrollProvider (this);\r
 \r
                     break;\r
                 }\r
-                case ComTypes::UIA_ScrollItemPatternId:\r
+                case UIA_ScrollItemPatternId:\r
                 {\r
                     if (isListOrTableCell (accessibilityHandler))\r
                         return new UIAScrollItemProvider (this);\r
@@ -345,6 +349,8 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPropertyValue (PROPERTYID propertyI
         const auto state   = accessibilityHandler.getCurrentState();\r
         const auto ignored = accessibilityHandler.isIgnored();\r
 \r
+        using namespace ComTypes::Constants;\r
+\r
         switch (propertyId)\r
         {\r
             case UIA_AutomationIdPropertyId:\r
@@ -389,7 +395,7 @@ JUCE_COMRESULT AccessibilityNativeHandle::GetPropertyValue (PROPERTYID propertyI
                     VariantHelpers::setBool (textInterface->isDisplayingProtectedText(), pRetVal);\r
 \r
                 break;\r
-            case ComTypes::UIA_IsPeripheralPropertyId:\r
+            case UIA_IsPeripheralPropertyId:\r
                 VariantHelpers::setBool (role == AccessibilityRole::tooltip\r
                                          || role == AccessibilityRole::popupMenu\r
                                          || role == AccessibilityRole::splashScreen,\r
index a00e6baddc75e420a6afd2ede78e5604d80d266e..0109d9d16b5f9a8c906e521f9c2c5380abcfe105 100644 (file)
@@ -26,9 +26,6 @@
 namespace juce\r
 {\r
 \r
-#define UIA_FullDescriptionPropertyId 30159\r
-#define UIA_IsDialogPropertyId        30174\r
-\r
 class AccessibilityNativeHandle  : public ComBaseClassHelper<IRawElementProviderSimple,\r
                                                              ComTypes::IRawElementProviderFragment,\r
                                                              ComTypes::IRawElementProviderFragmentRoot>\r
index cb07817ba75fa15b67800033f95152b84cc91437..0f6a08f5e6f2742b673427b3aac5666833e588f2 100644 (file)
@@ -136,6 +136,68 @@ enum ScrollAmount
     ScrollAmount_SmallIncrement = 4\r
 };\r
 \r
+namespace Constants\r
+{\r
+\r
+#undef UIA_InvokePatternId\r
+#undef UIA_SelectionPatternId\r
+#undef UIA_ValuePatternId\r
+#undef UIA_RangeValuePatternId\r
+#undef UIA_ScrollPatternId\r
+#undef UIA_ExpandCollapsePatternId\r
+#undef UIA_GridPatternId\r
+#undef UIA_GridItemPatternId\r
+#undef UIA_WindowPatternId\r
+#undef UIA_SelectionItemPatternId\r
+#undef UIA_TablePatternId\r
+#undef UIA_TableItemPatternId\r
+#undef UIA_TextPatternId\r
+#undef UIA_TogglePatternId\r
+#undef UIA_TransformPatternId\r
+#undef UIA_ScrollItemPatternId\r
+#undef UIA_TextPattern2Id\r
+#undef UIA_StructureChangedEventId\r
+#undef UIA_MenuOpenedEventId\r
+#undef UIA_AutomationFocusChangedEventId\r
+#undef UIA_MenuClosedEventId\r
+#undef UIA_LayoutInvalidatedEventId\r
+#undef UIA_Invoke_InvokedEventId\r
+#undef UIA_SelectionItem_ElementSelectedEventId\r
+#undef UIA_Text_TextSelectionChangedEventId\r
+#undef UIA_Text_TextChangedEventId\r
+#undef UIA_Window_WindowOpenedEventId\r
+#undef UIA_Window_WindowClosedEventId\r
+#undef UIA_IsPeripheralPropertyId\r
+#undef UIA_FullDescriptionPropertyId\r
+#undef UIA_IsDialogPropertyId\r
+#undef UIA_IsReadOnlyAttributeId\r
+#undef UIA_CaretPositionAttributeId\r
+#undef UIA_ButtonControlTypeId\r
+#undef UIA_CheckBoxControlTypeId\r
+#undef UIA_ComboBoxControlTypeId\r
+#undef UIA_EditControlTypeId\r
+#undef UIA_HyperlinkControlTypeId\r
+#undef UIA_ImageControlTypeId\r
+#undef UIA_ListItemControlTypeId\r
+#undef UIA_ListControlTypeId\r
+#undef UIA_MenuBarControlTypeId\r
+#undef UIA_MenuItemControlTypeId\r
+#undef UIA_ProgressBarControlTypeId\r
+#undef UIA_RadioButtonControlTypeId\r
+#undef UIA_ScrollBarControlTypeId\r
+#undef UIA_SliderControlTypeId\r
+#undef UIA_TextControlTypeId\r
+#undef UIA_ToolTipControlTypeId\r
+#undef UIA_TreeControlTypeId\r
+#undef UIA_TreeItemControlTypeId\r
+#undef UIA_CustomControlTypeId\r
+#undef UIA_GroupControlTypeId\r
+#undef UIA_DataItemControlTypeId\r
+#undef UIA_WindowControlTypeId\r
+#undef UIA_HeaderControlTypeId\r
+#undef UIA_HeaderItemControlTypeId\r
+#undef UIA_TableControlTypeId\r
+\r
 const long UIA_InvokePatternId = 10000;\r
 const long UIA_SelectionPatternId = 10001;\r
 const long UIA_ValuePatternId = 10002;\r
@@ -165,6 +227,8 @@ const long UIA_Text_TextChangedEventId = 20015;
 const long UIA_Window_WindowOpenedEventId = 20016;\r
 const long UIA_Window_WindowClosedEventId = 20017;\r
 const long UIA_IsPeripheralPropertyId = 30150;\r
+const long UIA_FullDescriptionPropertyId = 30159;\r
+const long UIA_IsDialogPropertyId = 30174;\r
 const long UIA_IsReadOnlyAttributeId = 40015;\r
 const long UIA_CaretPositionAttributeId = 40038;\r
 const long UIA_ButtonControlTypeId = 50000;\r
@@ -193,6 +257,8 @@ const long UIA_HeaderControlTypeId = 50034;
 const long UIA_HeaderItemControlTypeId = 50035;\r
 const long UIA_TableControlTypeId = 50036;\r
 \r
+} // namespace Constants\r
+\r
 interface IRawElementProviderFragmentRoot;\r
 interface IRawElementProviderFragment;\r
 \r
index de1772f0c082b8273f73e368b3fd712a09ccd117..ca6fb8af5634b54b7986638f0c2ebcb50b7f9519 100644 (file)
@@ -66,9 +66,11 @@ private:
 \r
         if (handler.getActions().invoke (AccessibilityActionType::showMenu))\r
         {\r
+            using namespace ComTypes::Constants;\r
+\r
             sendAccessibilityAutomationEvent (handler, handler.getCurrentState().isExpanded()\r
-                                                           ? ComTypes::UIA_MenuOpenedEventId\r
-                                                           : ComTypes::UIA_MenuClosedEventId);\r
+                                                           ? UIA_MenuOpenedEventId\r
+                                                           : UIA_MenuClosedEventId);\r
 \r
             return S_OK;\r
         }\r
index e991abb614e8f181a6203bf0b86d334974ccb215..ff8a4239ce9754d29d026b8bbd00fed405e385b9 100644 (file)
@@ -43,8 +43,10 @@ public:
 \r
         if (handler.getActions().invoke (AccessibilityActionType::press))\r
         {\r
+            using namespace ComTypes::Constants;\r
+\r
             if (isElementValid())\r
-                sendAccessibilityAutomationEvent (handler, ComTypes::UIA_Invoke_InvokedEventId);\r
+                sendAccessibilityAutomationEvent (handler, UIA_Invoke_InvokedEventId);\r
 \r
             return S_OK;\r
         }\r
index dc0427a84201e0d7d28512be58cc1e9f1f4531d1..874cb3b3d30c34321a31bd4294a28a0a5fe8d487 100644 (file)
@@ -49,8 +49,10 @@ public:
 \r
         if (isRadioButton)\r
         {\r
+            using namespace ComTypes::Constants;\r
+\r
             handler.getActions().invoke (AccessibilityActionType::press);\r
-            sendAccessibilityAutomationEvent (handler, ComTypes::UIA_SelectionItem_ElementSelectedEventId);\r
+            sendAccessibilityAutomationEvent (handler, UIA_SelectionItem_ElementSelectedEventId);\r
 \r
             return S_OK;\r
         }\r
index 7a6224c82ec9a7c82d617ee6135acccc90972ed2..6b9b0ff46a5d5cc960ce803d106d8add36e060d3 100644 (file)
@@ -303,15 +303,17 @@ private:
             {\r
                 VariantHelpers::clear (pRetVal);\r
 \r
+                using namespace ComTypes::Constants;\r
+\r
                 switch (attributeId)\r
                 {\r
-                    case ComTypes::UIA_IsReadOnlyAttributeId:\r
+                    case UIA_IsReadOnlyAttributeId:\r
                     {\r
                         VariantHelpers::setBool (textInterface.isReadOnly(), pRetVal);\r
                         break;\r
                     }\r
 \r
-                    case ComTypes::UIA_CaretPositionAttributeId:\r
+                    case UIA_CaretPositionAttributeId:\r
                     {\r
                         auto cursorPos = textInterface.getTextInsertionOffset();\r
 \r
index fc0371a9eac7b8a3a6f4c59069f6d2def92f735a..9a82e2c19b948cf5cb65a741e093e7d7b450aa30 100644 (file)
@@ -32,9 +32,20 @@ import android.graphics.Canvas;
 import android.graphics.ColorMatrix;\r
 import android.graphics.ColorMatrixColorFilter;\r
 import android.graphics.Paint;\r
+import android.graphics.Point;\r
 import android.graphics.Rect;\r
+import android.os.Build;\r
+import android.text.Selection;\r
+import android.text.SpanWatcher;\r
+import android.text.Spannable;\r
+import android.text.Spanned;\r
+import android.text.TextWatcher;\r
+import android.util.Pair;\r
 import android.os.Bundle;\r
+import android.text.Editable;\r
 import android.text.InputType;\r
+import android.text.SpannableStringBuilder;\r
+import android.view.Choreographer;\r
 import android.view.KeyEvent;\r
 import android.view.MotionEvent;\r
 import android.view.View;\r
@@ -50,10 +61,11 @@ import android.view.inputmethod.InputMethodManager;
 \r
 import java.lang.reflect.Method;\r
 import java.util.ArrayList;\r
+\r
 import java.util.List;\r
 \r
 public final class ComponentPeerView extends ViewGroup\r
-        implements View.OnFocusChangeListener, Application.ActivityLifecycleCallbacks\r
+        implements View.OnFocusChangeListener, Application.ActivityLifecycleCallbacks, Choreographer.FrameCallback\r
 {\r
     public ComponentPeerView (Context context, boolean opaque_, long host)\r
     {\r
@@ -62,9 +74,10 @@ public final class ComponentPeerView extends ViewGroup
         if (Application.class.isInstance (context))\r
         {\r
             ((Application) context).registerActivityLifecycleCallbacks (this);\r
-        } else\r
+        }\r
+        else\r
         {\r
-            ((Application) context.getApplicationContext ()).registerActivityLifecycleCallbacks (this);\r
+            ((Application) context.getApplicationContext()).registerActivityLifecycleCallbacks (this);\r
         }\r
 \r
         this.host = host;\r
@@ -76,7 +89,7 @@ public final class ComponentPeerView extends ViewGroup
         setOnFocusChangeListener (this);\r
 \r
         // swap red and blue colours to match internal opengl texture format\r
-        ColorMatrix colorMatrix = new ColorMatrix ();\r
+        ColorMatrix colorMatrix = new ColorMatrix();\r
 \r
         float[] colorTransform = {0, 0, 1.0f, 0, 0,\r
                 0, 1.0f, 0, 0, 0,\r
@@ -90,10 +103,12 @@ public final class ComponentPeerView extends ViewGroup
 \r
         try\r
         {\r
-            method = getClass ().getMethod ("setLayerType", int.class, Paint.class);\r
-        } catch (SecurityException e)\r
+            method = getClass().getMethod ("setLayerType", int.class, Paint.class);\r
+        }\r
+        catch (SecurityException e)\r
         {\r
-        } catch (NoSuchMethodException e)\r
+        }\r
+        catch (NoSuchMethodException e)\r
         {\r
         }\r
 \r
@@ -103,17 +118,22 @@ public final class ComponentPeerView extends ViewGroup
             {\r
                 int layerTypeNone = 0;\r
                 method.invoke (this, layerTypeNone, null);\r
-            } catch (java.lang.IllegalArgumentException e)\r
+            }\r
+            catch (java.lang.IllegalArgumentException e)\r
             {\r
-            } catch (java.lang.IllegalAccessException e)\r
+            }\r
+            catch (java.lang.IllegalAccessException e)\r
             {\r
-            } catch (java.lang.reflect.InvocationTargetException e)\r
+            }\r
+            catch (java.lang.reflect.InvocationTargetException e)\r
             {\r
             }\r
         }\r
+\r
+        Choreographer.getInstance().postFrameCallback (this);\r
     }\r
 \r
-    public void clear ()\r
+    public void clear()\r
     {\r
         host = 0;\r
     }\r
@@ -130,15 +150,28 @@ public final class ComponentPeerView extends ViewGroup
         handlePaint (host, canvas, paint);\r
     }\r
 \r
+    private native void handleDoFrame (long host, long frameTimeNanos);\r
+\r
     @Override\r
-    public boolean isOpaque ()\r
+    public void doFrame (long frameTimeNanos)\r
+    {\r
+        if (host == 0)\r
+            return;\r
+\r
+        handleDoFrame (host, frameTimeNanos);\r
+\r
+        Choreographer.getInstance().postFrameCallback (this);\r
+    }\r
+\r
+    @Override\r
+    public boolean isOpaque()\r
     {\r
         return opaque;\r
     }\r
 \r
     private final boolean opaque;\r
     private long host;\r
-    private final Paint paint = new Paint ();\r
+    private final Paint paint = new Paint();\r
 \r
     //==============================================================================\r
     private native void handleMouseDown (long host, int index, float x, float y, long time);\r
@@ -152,25 +185,25 @@ public final class ComponentPeerView extends ViewGroup
         if (host == 0)\r
             return false;\r
 \r
-        int action = event.getAction ();\r
-        long time = event.getEventTime ();\r
+        int action = event.getAction();\r
+        long time = event.getEventTime();\r
 \r
         switch (action & MotionEvent.ACTION_MASK)\r
         {\r
             case MotionEvent.ACTION_DOWN:\r
-                handleMouseDown (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time);\r
+                handleMouseDown (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time);\r
                 return true;\r
 \r
             case MotionEvent.ACTION_CANCEL:\r
             case MotionEvent.ACTION_UP:\r
-                handleMouseUp (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time);\r
+                handleMouseUp (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time);\r
                 return true;\r
 \r
             case MotionEvent.ACTION_MOVE:\r
             {\r
-                handleMouseDrag (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time);\r
+                handleMouseDrag (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time);\r
 \r
-                int n = event.getPointerCount ();\r
+                int n = event.getPointerCount();\r
 \r
                 if (n > 1)\r
                 {\r
@@ -190,8 +223,9 @@ public final class ComponentPeerView extends ViewGroup
 \r
                 if (i == 0)\r
                 {\r
-                    handleMouseUp (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time);\r
-                } else\r
+                    handleMouseUp (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time);\r
+                }\r
+                else\r
                 {\r
                     int point[] = new int[2];\r
                     getLocationOnScreen (point);\r
@@ -207,8 +241,9 @@ public final class ComponentPeerView extends ViewGroup
 \r
                 if (i == 0)\r
                 {\r
-                    handleMouseDown (host, event.getPointerId (0), event.getRawX (), event.getRawY (), time);\r
-                } else\r
+                    handleMouseDown (host, event.getPointerId (0), event.getRawX(), event.getRawY(), time);\r
+                }\r
+                else\r
                 {\r
                     int point[] = new int[2];\r
                     getLocationOnScreen (point);\r
@@ -237,32 +272,132 @@ public final class ComponentPeerView extends ViewGroup
         return false;\r
     }\r
 \r
+    //==============================================================================\r
+    public static class TextInputTarget\r
+    {\r
+        public TextInputTarget (long owner) { host = owner; }\r
+\r
+        public boolean isTextInputActive()                                      { return ComponentPeerView.textInputTargetIsTextInputActive (host); }\r
+        public int getHighlightedRegionBegin()                                  { return ComponentPeerView.textInputTargetGetHighlightedRegionBegin (host); }\r
+        public int getHighlightedRegionEnd()                                    { return ComponentPeerView.textInputTargetGetHighlightedRegionEnd (host); }\r
+        public void setHighlightedRegion (int b, int e)                         {        ComponentPeerView.textInputTargetSetHighlightedRegion (host, b, e); }\r
+        public String getTextInRange (int b, int e)                             { return ComponentPeerView.textInputTargetGetTextInRange (host, b, e); }\r
+        public void insertTextAtCaret (String text)                             {        ComponentPeerView.textInputTargetInsertTextAtCaret (host, text); }\r
+        public int getCaretPosition()                                           { return ComponentPeerView.textInputTargetGetCaretPosition (host); }\r
+        public int getTotalNumChars()                                           { return ComponentPeerView.textInputTargetGetTotalNumChars (host); }\r
+        public int getCharIndexForPoint (Point point)                           { return ComponentPeerView.textInputTargetGetCharIndexForPoint (host, point); }\r
+        public int getKeyboardType()                                            { return ComponentPeerView.textInputTargetGetKeyboardType (host); }\r
+        public void setTemporaryUnderlining (List<Pair<Integer, Integer>> list) {        ComponentPeerView.textInputTargetSetTemporaryUnderlining (host, list); }\r
+\r
+        //==============================================================================\r
+        private final long host;\r
+    }\r
+\r
+    private native static boolean   textInputTargetIsTextInputActive (long host);\r
+    private native static int       textInputTargetGetHighlightedRegionBegin (long host);\r
+    private native static int       textInputTargetGetHighlightedRegionEnd (long host);\r
+    private native static void      textInputTargetSetHighlightedRegion (long host, int begin, int end);\r
+    private native static String    textInputTargetGetTextInRange (long host, int begin, int end);\r
+    private native static void      textInputTargetInsertTextAtCaret (long host, String text);\r
+    private native static int       textInputTargetGetCaretPosition (long host);\r
+    private native static int       textInputTargetGetTotalNumChars (long host);\r
+    private native static int       textInputTargetGetCharIndexForPoint (long host, Point point);\r
+    private native static int       textInputTargetGetKeyboardType (long host);\r
+    private native static void      textInputTargetSetTemporaryUnderlining (long host, List<Pair<Integer, Integer>> list);\r
+\r
+    private native long getFocusedTextInputTargetPointer (long host);\r
+\r
+    private TextInputTarget getFocusedTextInputTarget (long host)\r
+    {\r
+        final long ptr = getFocusedTextInputTargetPointer (host);\r
+        return ptr != 0 ? new TextInputTarget (ptr) : null;\r
+    }\r
+\r
     //==============================================================================\r
     private native void handleKeyDown (long host, int keycode, int textchar, int kbFlags);\r
     private native void handleKeyUp (long host, int keycode, int textchar);\r
     private native void handleBackButton (long host);\r
     private native void handleKeyboardHidden (long host);\r
 \r
-    public void showKeyboard (String type)\r
+    private static int getInputTypeForJuceVirtualKeyboardType (int type)\r
     {\r
-        InputMethodManager imm = (InputMethodManager) getContext ().getSystemService (Context.INPUT_METHOD_SERVICE);\r
-\r
-        if (imm != null)\r
+        switch (type)\r
         {\r
-            if (type.length () > 0)\r
-            {\r
-                imm.showSoftInput (this, android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT);\r
-                imm.setInputMethod (getWindowToken (), type);\r
-                keyboardDismissListener.startListening ();\r
-            } else\r
-            {\r
-                imm.hideSoftInputFromWindow (getWindowToken (), 0);\r
-                keyboardDismissListener.stopListening ();\r
-            }\r
+            case 0:                                             // textKeyboard\r
+                return InputType.TYPE_CLASS_TEXT\r
+                     | InputType.TYPE_TEXT_VARIATION_NORMAL\r
+                     | InputType.TYPE_TEXT_FLAG_MULTI_LINE\r
+                     | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;\r
+            case 1:                                             // numericKeyboard\r
+                return InputType.TYPE_CLASS_NUMBER\r
+                     | InputType.TYPE_NUMBER_VARIATION_NORMAL;\r
+            case 2:                                             // decimalKeyboard\r
+                return InputType.TYPE_CLASS_NUMBER\r
+                     | InputType.TYPE_NUMBER_VARIATION_NORMAL\r
+                     | InputType.TYPE_NUMBER_FLAG_DECIMAL;\r
+            case 3:                                             // urlKeyboard\r
+                return InputType.TYPE_CLASS_TEXT\r
+                     | InputType.TYPE_TEXT_VARIATION_URI\r
+                     | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;\r
+            case 4:                                             // emailAddressKeyboard\r
+                return InputType.TYPE_CLASS_TEXT\r
+                     | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS\r
+                     | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;\r
+            case 5:                                             // phoneNumberKeyboard\r
+                return InputType.TYPE_CLASS_PHONE;\r
+            case 6:                                             // passwordKeyboard\r
+                return InputType.TYPE_CLASS_TEXT\r
+                     | InputType.TYPE_TEXT_VARIATION_PASSWORD\r
+                     | InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS;\r
         }\r
+\r
+        return 0;\r
+    }\r
+\r
+    InputMethodManager getInputMethodManager()\r
+    {\r
+        return (InputMethodManager) getContext().getSystemService (Context.INPUT_METHOD_SERVICE);\r
     }\r
 \r
-    public void backButtonPressed ()\r
+    public void closeInputMethodContext()\r
+    {\r
+        InputMethodManager imm = getInputMethodManager();\r
+\r
+        if (imm == null)\r
+            return;\r
+\r
+        if (cachedConnection != null)\r
+            cachedConnection.closeConnection();\r
+\r
+        imm.restartInput (this);\r
+    }\r
+\r
+    public void showKeyboard (int virtualKeyboardType, int selectionStart, int selectionEnd)\r
+    {\r
+        InputMethodManager imm = getInputMethodManager();\r
+\r
+        if (imm == null)\r
+            return;\r
+\r
+        // restartingInput causes a call back to onCreateInputConnection, where we'll pick\r
+        // up the correct keyboard characteristics to use for the focused TextInputTarget.\r
+        imm.restartInput (this);\r
+        imm.showSoftInput (this, 0);\r
+        keyboardDismissListener.startListening();\r
+    }\r
+\r
+    public void hideKeyboard()\r
+    {\r
+        InputMethodManager imm = getInputMethodManager();\r
+\r
+        if (imm == null)\r
+            return;\r
+\r
+        imm.hideSoftInputFromWindow (getWindowToken(), 0);\r
+        keyboardDismissListener.stopListening();\r
+    }\r
+\r
+    public void backButtonPressed()\r
     {\r
         if (host == 0)\r
             return;\r
@@ -276,6 +411,11 @@ public final class ComponentPeerView extends ViewGroup
         if (host == 0)\r
             return false;\r
 \r
+        // The key event may move the cursor, or in some cases it might enter characters (e.g.\r
+        // digits). In this case, we need to reset the IME so that it's aware of the new contents\r
+        // of the TextInputTarget.\r
+        closeInputMethodContext();\r
+\r
         switch (keyCode)\r
         {\r
             case KeyEvent.KEYCODE_VOLUME_UP:\r
@@ -283,7 +423,7 @@ public final class ComponentPeerView extends ViewGroup
                 return super.onKeyDown (keyCode, event);\r
             case KeyEvent.KEYCODE_BACK:\r
             {\r
-                backButtonPressed ();\r
+                backButtonPressed();\r
                 return true;\r
             }\r
 \r
@@ -293,8 +433,9 @@ public final class ComponentPeerView extends ViewGroup
 \r
         handleKeyDown (host,\r
                        keyCode,\r
-                       event.getUnicodeChar (),\r
-                       event.getMetaState ());\r
+                       event.getUnicodeChar(),\r
+                       event.getMetaState());\r
+\r
         return true;\r
     }\r
 \r
@@ -304,7 +445,7 @@ public final class ComponentPeerView extends ViewGroup
         if (host == 0)\r
             return false;\r
 \r
-        handleKeyUp (host, keyCode, event.getUnicodeChar ());\r
+        handleKeyUp (host, keyCode, event.getUnicodeChar());\r
         return true;\r
     }\r
 \r
@@ -314,17 +455,17 @@ public final class ComponentPeerView extends ViewGroup
         if (host == 0)\r
             return false;\r
 \r
-        if (keyCode != KeyEvent.KEYCODE_UNKNOWN || event.getAction () != KeyEvent.ACTION_MULTIPLE)\r
+        if (keyCode != KeyEvent.KEYCODE_UNKNOWN || (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && event.getAction() != KeyEvent.ACTION_MULTIPLE))\r
             return super.onKeyMultiple (keyCode, count, event);\r
 \r
-        if (event.getCharacters () != null)\r
+        if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && event.getCharacters() != null)\r
         {\r
-            int utf8Char = event.getCharacters ().codePointAt (0);\r
+            int utf8Char = event.getCharacters().codePointAt (0);\r
 \r
             handleKeyDown (host,\r
                            keyCode,\r
                            utf8Char,\r
-                           event.getMetaState ());\r
+                           event.getMetaState());\r
             return true;\r
         }\r
 \r
@@ -339,39 +480,40 @@ public final class ComponentPeerView extends ViewGroup
             view = viewToUse;\r
         }\r
 \r
-        private void startListening ()\r
+        private void startListening()\r
         {\r
-            view.getViewTreeObserver ().addOnGlobalLayoutListener (viewTreeObserver);\r
+            view.getViewTreeObserver().addOnGlobalLayoutListener (viewTreeObserver);\r
         }\r
 \r
-        private void stopListening ()\r
+        private void stopListening()\r
         {\r
-            view.getViewTreeObserver ().removeGlobalOnLayoutListener (viewTreeObserver);\r
+            view.getViewTreeObserver().removeOnGlobalLayoutListener (viewTreeObserver);\r
         }\r
 \r
         private class TreeObserver implements ViewTreeObserver.OnGlobalLayoutListener\r
         {\r
-            TreeObserver ()\r
+            TreeObserver()\r
             {\r
                 keyboardShown = false;\r
             }\r
 \r
             @Override\r
-            public void onGlobalLayout ()\r
+            public void onGlobalLayout()\r
             {\r
-                Rect r = new Rect ();\r
+                Rect r = new Rect();\r
 \r
-                View parentView = getRootView ();\r
+                View parentView = getRootView();\r
                 int diff;\r
 \r
                 if (parentView == null)\r
                 {\r
                     getWindowVisibleDisplayFrame (r);\r
-                    diff = getHeight () - (r.bottom - r.top);\r
-                } else\r
+                    diff = getHeight() - (r.bottom - r.top);\r
+                }\r
+                else\r
                 {\r
                     parentView.getWindowVisibleDisplayFrame (r);\r
-                    diff = parentView.getHeight () - (r.bottom - r.top);\r
+                    diff = parentView.getHeight() - (r.bottom - r.top);\r
                 }\r
 \r
                 // Arbitrary threshold, surely keyboard would take more than 20 pix.\r
@@ -381,7 +523,7 @@ public final class ComponentPeerView extends ViewGroup
                     handleKeyboardHidden (view.host);\r
                 }\r
 \r
-                if (!keyboardShown && diff > 20)\r
+                if (! keyboardShown && diff > 20)\r
                     keyboardShown = true;\r
             }\r
 \r
@@ -389,26 +531,219 @@ public final class ComponentPeerView extends ViewGroup
         }\r
 \r
         private final ComponentPeerView view;\r
-        private final TreeObserver viewTreeObserver = new TreeObserver ();\r
+        private final TreeObserver viewTreeObserver = new TreeObserver();\r
     }\r
 \r
     private final KeyboardDismissListener keyboardDismissListener = new KeyboardDismissListener (this);\r
 \r
-    // this is here to make keyboard entry work on a Galaxy Tab2 10.1\r
+    //==============================================================================\r
+    // This implementation is quite similar to the ChangeListener in Android's built-in TextView.\r
+    private static final class ChangeWatcher implements SpanWatcher, TextWatcher\r
+    {\r
+        public ChangeWatcher (ComponentPeerView viewIn, Editable editableIn, TextInputTarget targetIn)\r
+        {\r
+            view = viewIn;\r
+            editable = editableIn;\r
+            target = targetIn;\r
+\r
+            updateEditableSelectionFromTarget (editable, target);\r
+        }\r
+\r
+        @Override\r
+        public void onSpanAdded (Spannable text, Object what, int start, int end)\r
+        {\r
+            updateTargetRangesFromEditable (editable, target);\r
+        }\r
+\r
+        @Override\r
+        public void onSpanRemoved (Spannable text, Object what, int start, int end)\r
+        {\r
+            updateTargetRangesFromEditable (editable, target);\r
+        }\r
+\r
+        @Override\r
+        public void onSpanChanged (Spannable text, Object what, int ostart, int oend, int nstart, int nend)\r
+        {\r
+            updateTargetRangesFromEditable (editable, target);\r
+        }\r
+\r
+        @Override\r
+        public void afterTextChanged (Editable s)\r
+        {\r
+        }\r
+\r
+        @Override\r
+        public void beforeTextChanged (CharSequence s, int start, int count, int after)\r
+        {\r
+            contentsBeforeChange = s.toString();\r
+        }\r
+\r
+        @Override\r
+        public void onTextChanged (CharSequence s, int start, int before, int count)\r
+        {\r
+            if (editable != s || contentsBeforeChange == null)\r
+                return;\r
+\r
+            final String newText = s.subSequence (start, start + count).toString();\r
+\r
+            int code = 0;\r
+\r
+            if (newText.endsWith ("\n") || newText.endsWith ("\r"))\r
+                code = KeyEvent.KEYCODE_ENTER;\r
+\r
+            if (newText.endsWith ("\t"))\r
+                code = KeyEvent.KEYCODE_TAB;\r
+\r
+            target.setHighlightedRegion (contentsBeforeChange.codePointCount (0, start),\r
+                                         contentsBeforeChange.codePointCount (0, start + before));\r
+            target.insertTextAtCaret (code != 0 ? newText.substring (0, newText.length() - 1)\r
+                                                : newText);\r
+\r
+            // Treating return/tab as individual keypresses rather than part of the composition\r
+            // sequence allows TextEditor onReturn and onTab to work as expected.\r
+            if (code != 0)\r
+                view.onKeyDown (code, new KeyEvent (KeyEvent.ACTION_DOWN, code));\r
+\r
+            updateTargetRangesFromEditable (editable, target);\r
+            contentsBeforeChange = null;\r
+        }\r
+\r
+        private static void updateEditableSelectionFromTarget (Editable editable, TextInputTarget text)\r
+        {\r
+            final int start = text.getHighlightedRegionBegin();\r
+            final int end   = text.getHighlightedRegionEnd();\r
+\r
+            if (start < 0 || end < 0)\r
+                return;\r
+\r
+            final String string = editable.toString();\r
+            Selection.setSelection (editable,\r
+                                    string.offsetByCodePoints (0, start),\r
+                                    string.offsetByCodePoints (0, end));\r
+        }\r
+\r
+        private static void updateTargetSelectionFromEditable (Editable editable, TextInputTarget target)\r
+        {\r
+            final int start = Selection.getSelectionStart (editable);\r
+            final int end   = Selection.getSelectionEnd   (editable);\r
+\r
+            if (start < 0 || end < 0)\r
+                return;\r
+\r
+            final String string = editable.toString();\r
+            target.setHighlightedRegion (string.codePointCount (0, start),\r
+                                         string.codePointCount (0, end));\r
+        }\r
+\r
+        private static List<Pair<Integer, Integer>> getUnderlinedRanges (Editable editable)\r
+        {\r
+            final int start = BaseInputConnection.getComposingSpanStart (editable);\r
+            final int end   = BaseInputConnection.getComposingSpanEnd   (editable);\r
+\r
+            if (start < 0 || end < 0)\r
+                return null;\r
+\r
+            final String string = editable.toString();\r
+\r
+            final ArrayList<Pair<Integer, Integer>> pairs = new ArrayList<>();\r
+            pairs.add (new Pair<> (string.codePointCount (0, start), string.codePointCount (0, end)));\r
+            return pairs;\r
+        }\r
+\r
+        private static void updateTargetCompositionRangesFromEditable (Editable editable, TextInputTarget target)\r
+        {\r
+            target.setTemporaryUnderlining (getUnderlinedRanges (editable));\r
+        }\r
+\r
+        private static void updateTargetRangesFromEditable (Editable editable, TextInputTarget target)\r
+        {\r
+            updateTargetSelectionFromEditable         (editable, target);\r
+            updateTargetCompositionRangesFromEditable (editable, target);\r
+        }\r
+\r
+        private final ComponentPeerView view;\r
+        private final TextInputTarget target;\r
+        private final Editable editable;\r
+        private String contentsBeforeChange;\r
+    }\r
+\r
+    private static final class Connection extends BaseInputConnection\r
+    {\r
+        Connection (ComponentPeerView viewIn, boolean fullEditor, TextInputTarget targetIn)\r
+        {\r
+            super (viewIn, fullEditor);\r
+            view = viewIn;\r
+            target = targetIn;\r
+        }\r
+\r
+        @Override\r
+        public Editable getEditable()\r
+        {\r
+            if (cached != null)\r
+                return cached;\r
+\r
+            if (target == null)\r
+                return cached = super.getEditable();\r
+\r
+            int length = target.getTotalNumChars();\r
+            String initialText = target.getTextInRange (0, length);\r
+            cached = new SpannableStringBuilder (initialText);\r
+            // Span the entire range of text, so that we pick up changes at any location.\r
+            // Use cached.length rather than target.getTotalNumChars here, because this\r
+            // range is in UTF-16 code units, rather than code points.\r
+            changeWatcher = new ChangeWatcher (view, cached, target);\r
+            cached.setSpan (changeWatcher, 0, cached.length(), Spanned.SPAN_INCLUSIVE_INCLUSIVE);\r
+            return cached;\r
+        }\r
+\r
+        /** Call this to stop listening for selection/composition updates.\r
+\r
+            We do this before closing the current input method context (e.g. when the user\r
+            taps on a text view to move the cursor), because otherwise the input system\r
+            might send another round of notifications *during* the restartInput call, after we've\r
+            requested that the input session should end.\r
+        */\r
+        @Override\r
+        public void closeConnection()\r
+        {\r
+            if (cached != null && changeWatcher != null)\r
+                cached.removeSpan (changeWatcher);\r
+\r
+            cached = null;\r
+            target = null;\r
+\r
+            super.closeConnection();\r
+        }\r
+\r
+        private ComponentPeerView view;\r
+        private TextInputTarget target;\r
+        private Editable cached;\r
+        private ChangeWatcher changeWatcher;\r
+    }\r
+\r
     @Override\r
     public InputConnection onCreateInputConnection (EditorInfo outAttrs)\r
     {\r
+        TextInputTarget focused = getFocusedTextInputTarget (host);\r
+\r
         outAttrs.actionLabel = "";\r
         outAttrs.hintText = "";\r
         outAttrs.initialCapsMode = 0;\r
-        outAttrs.initialSelEnd = outAttrs.initialSelStart = -1;\r
+        outAttrs.initialSelStart = focused != null ? focused.getHighlightedRegionBegin() : -1;\r
+        outAttrs.initialSelEnd   = focused != null ? focused.getHighlightedRegionEnd()   : -1;\r
         outAttrs.label = "";\r
-        outAttrs.imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_EXTRACT_UI;\r
-        outAttrs.inputType = InputType.TYPE_NULL;\r
-\r
-        return new BaseInputConnection (this, false);\r
+        outAttrs.imeOptions = EditorInfo.IME_ACTION_UNSPECIFIED\r
+                            | EditorInfo.IME_FLAG_NO_EXTRACT_UI\r
+                            | EditorInfo.IME_FLAG_NO_ENTER_ACTION;\r
+        outAttrs.inputType = focused != null ? getInputTypeForJuceVirtualKeyboardType (focused.getKeyboardType())\r
+                                             : 0;\r
+\r
+        cachedConnection = new Connection (this, true, focused);\r
+        return cachedConnection;\r
     }\r
 \r
+    private Connection cachedConnection;\r
+\r
     //==============================================================================\r
     @Override\r
     protected void onSizeChanged (int w, int h, int oldw, int oldh)\r
@@ -447,11 +782,13 @@ public final class ComponentPeerView extends ViewGroup
         Method systemUIVisibilityMethod = null;\r
         try\r
         {\r
-            systemUIVisibilityMethod = this.getClass ().getMethod ("setSystemUiVisibility", int.class);\r
-        } catch (SecurityException e)\r
+            systemUIVisibilityMethod = this.getClass().getMethod ("setSystemUiVisibility", int.class);\r
+        }\r
+        catch (SecurityException e)\r
         {\r
             return;\r
-        } catch (NoSuchMethodException e)\r
+        }\r
+        catch (NoSuchMethodException e)\r
         {\r
             return;\r
         }\r
@@ -460,18 +797,21 @@ public final class ComponentPeerView extends ViewGroup
         try\r
         {\r
             systemUIVisibilityMethod.invoke (this, visibility);\r
-        } catch (java.lang.IllegalArgumentException e)\r
+        }\r
+        catch (java.lang.IllegalArgumentException e)\r
         {\r
-        } catch (java.lang.IllegalAccessException e)\r
+        }\r
+        catch (java.lang.IllegalAccessException e)\r
         {\r
-        } catch (java.lang.reflect.InvocationTargetException e)\r
+        }\r
+        catch (java.lang.reflect.InvocationTargetException e)\r
         {\r
         }\r
     }\r
 \r
-    public boolean isVisible ()\r
+    public boolean isVisible()\r
     {\r
-        return getVisibility () == VISIBLE;\r
+        return getVisibility() == VISIBLE;\r
     }\r
 \r
     public void setVisible (boolean b)\r
@@ -556,11 +896,22 @@ public final class ComponentPeerView extends ViewGroup
             if (host == 0)\r
                 return null;\r
 \r
-            final AccessibilityNodeInfo nodeInfo = AccessibilityNodeInfo.obtain (view, virtualViewId);\r
+            final AccessibilityNodeInfo nodeInfo;\r
+\r
+            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.R)\r
+            {\r
+                nodeInfo = new AccessibilityNodeInfo (view, virtualViewId);\r
+            }\r
+            else\r
+            {\r
+                nodeInfo = AccessibilityNodeInfo.obtain (view, virtualViewId);\r
+            }\r
 \r
             if (! populateAccessibilityNodeInfo (host, virtualViewId, nodeInfo))\r
             {\r
-                nodeInfo.recycle();\r
+                if (android.os.Build.VERSION.SDK_INT < android.os.Build.VERSION_CODES.R)\r
+                    nodeInfo.recycle();\r
+\r
                 return null;\r
             }\r
 \r
@@ -601,10 +952,10 @@ public final class ComponentPeerView extends ViewGroup
     }\r
 \r
     private final JuceAccessibilityNodeProvider nodeProvider = new JuceAccessibilityNodeProvider (this);\r
-    private final AccessibilityManager accessibilityManager = (AccessibilityManager) getContext ().getSystemService (Context.ACCESSIBILITY_SERVICE);\r
+    private final AccessibilityManager accessibilityManager = (AccessibilityManager) getContext().getSystemService (Context.ACCESSIBILITY_SERVICE);\r
 \r
     @Override\r
-    public AccessibilityNodeProvider getAccessibilityNodeProvider ()\r
+    public AccessibilityNodeProvider getAccessibilityNodeProvider()\r
     {\r
         return nodeProvider;\r
     }\r
index a89dc646c1b2000330f13ec51eb6ec179f1469f6..61f9a070e82f53eb4032cb2961e76b6086b8da5c 100644 (file)
@@ -34,7 +34,6 @@ public final class JuceContentProviderFileObserver extends FileObserver
     public JuceContentProviderFileObserver (long hostToUse, String path, int mask)\r
     {\r
         super (path, mask);\r
-\r
         host = hostToUse;\r
     }\r
 \r
index ba3f337698a53006de08ff6ed96ed8ae63c1b005..9330d28dec5cd5b09e67d4d85aba138e2eea2438 100644 (file)
@@ -101,7 +101,7 @@ public:
     class Owner\r
     {\r
     public:\r
-        virtual ~Owner() {}\r
+        virtual ~Owner() = default;\r
 \r
         virtual void cursorClosed (const AndroidContentSharerCursor&) = 0;\r
     };\r
@@ -121,9 +121,9 @@ public:
 \r
     jobject getNativeCursor() { return cursor.get(); }\r
 \r
-    void cursorClosed()\r
+    static void cursorClosed (JNIEnv*, AndroidContentSharerCursor& t)\r
     {\r
-        MessageManager::callAsync ([this] { owner.cursorClosed (*this); });\r
+        MessageManager::callAsync ([&t] { t.owner.cursorClosed (t); });\r
     }\r
 \r
     void addRow (LocalRef<jobjectArray>& values)\r
@@ -141,20 +141,12 @@ private:
     #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
      METHOD (addRow,      "addRow", "([Ljava/lang/Object;)V") \\r
      METHOD (constructor, "<init>", "(J[Ljava/lang/String;)V") \\r
-     CALLBACK (contentSharerCursorClosed, "contentSharerCursorClosed", "(J)V") \\r
+     CALLBACK (generatedCallback<&AndroidContentSharerCursor::cursorClosed>, "contentSharerCursorClosed", "(J)V") \\r
 \r
-    DECLARE_JNI_CLASS_WITH_BYTECODE (JuceContentProviderCursor, "com/rmsl/juce/JuceContentProviderCursor", 16, javaJuceContentProviderCursor, sizeof (javaJuceContentProviderCursor))\r
+    DECLARE_JNI_CLASS_WITH_BYTECODE (JuceContentProviderCursor, "com/rmsl/juce/JuceContentProviderCursor", 16, javaJuceContentProviderCursor)\r
     #undef JNI_CLASS_MEMBERS\r
-\r
-    static void JNICALL contentSharerCursorClosed (JNIEnv*, jobject, jlong host)\r
-    {\r
-        if (auto* myself = reinterpret_cast<AndroidContentSharerCursor*> (host))\r
-            myself->cursorClosed();\r
-    }\r
 };\r
 \r
-AndroidContentSharerCursor::JuceContentProviderCursor_Class AndroidContentSharerCursor::JuceContentProviderCursor;\r
-\r
 //==============================================================================\r
 class AndroidContentSharerFileObserver\r
 {\r
@@ -184,10 +176,8 @@ public:
         env->CallVoidMethod (fileObserver, JuceContentProviderFileObserver.startWatching);\r
     }\r
 \r
-    void onFileEvent (int event, const LocalRef<jstring>& path)\r
+    void onFileEvent (int event, [[maybe_unused]] const LocalRef<jstring>& path)\r
     {\r
-        ignoreUnused (path);\r
-\r
         if (event == open)\r
         {\r
             ++numOpenedHandles;\r
@@ -230,20 +220,17 @@ private:
      METHOD (constructor,   "<init>",        "(JLjava/lang/String;I)V") \\r
      METHOD (startWatching, "startWatching", "()V") \\r
      METHOD (stopWatching,  "stopWatching",  "()V") \\r
-     CALLBACK (contentSharerFileObserverEvent, "contentSharerFileObserverEvent", "(JILjava/lang/String;)V") \\r
+     CALLBACK (generatedCallback<&AndroidContentSharerFileObserver::onFileEventCallback>, "contentSharerFileObserverEvent", "(JILjava/lang/String;)V") \\r
 \r
-    DECLARE_JNI_CLASS_WITH_BYTECODE (JuceContentProviderFileObserver, "com/rmsl/juce/JuceContentProviderFileObserver", 16, javaJuceContentProviderFileObserver, sizeof (javaJuceContentProviderFileObserver))\r
+    DECLARE_JNI_CLASS_WITH_BYTECODE (JuceContentProviderFileObserver, "com/rmsl/juce/JuceContentProviderFileObserver", 16, javaJuceContentProviderFileObserver)\r
     #undef JNI_CLASS_MEMBERS\r
 \r
-    static void JNICALL contentSharerFileObserverEvent (JNIEnv*, jobject /*fileObserver*/, jlong host, int event, jstring path)\r
+    static void onFileEventCallback (JNIEnv*, AndroidContentSharerFileObserver& t, jint event, jstring path)\r
     {\r
-        if (auto* myself = reinterpret_cast<AndroidContentSharerFileObserver*> (host))\r
-            myself->onFileEvent (event, LocalRef<jstring> (path));\r
+        t.onFileEvent (event, LocalRef<jstring> (path));\r
     }\r
 };\r
 \r
-AndroidContentSharerFileObserver::JuceContentProviderFileObserver_Class AndroidContentSharerFileObserver::JuceContentProviderFileObserver;\r
-\r
 //==============================================================================\r
 class AndroidContentSharerPrepareFilesThread    : private Thread\r
 {\r
@@ -513,10 +500,8 @@ public:
 \r
     //==============================================================================\r
     jobject openFile (const LocalRef<jobject>& contentProvider,\r
-                      const LocalRef<jobject>& uri, const LocalRef<jstring>& mode)\r
+                      const LocalRef<jobject>& uri, [[maybe_unused]] const LocalRef<jstring>& mode)\r
     {\r
-        ignoreUnused (mode);\r
-\r
         WeakReference<ContentSharerNativeImpl> weakRef (this);\r
 \r
         if (weakRef == nullptr)\r
@@ -895,6 +880,4 @@ ContentSharer::Pimpl* ContentSharer::createPimpl()
     return new ContentSharerNativeImpl (*this);\r
 }\r
 \r
-ContentSharer::ContentSharerNativeImpl::JuceSharingContentProvider_Class ContentSharer::ContentSharerNativeImpl::JuceSharingContentProvider;\r
-\r
 } // namespace juce\r
index 53c2456e456838666dfc6910b76fcf13982f953d..b28166e04621465653e876cc7f3ff4f05189dc13 100644 (file)
@@ -277,4 +277,10 @@ bool FileChooser::isPlatformDialogAvailable()
    #endif\r
 }\r
 \r
+void FileChooser::registerCustomMimeTypeForFileExtension (const String& mimeType,\r
+                                                          const String& fileExtension)\r
+{\r
+    MimeTypeTable::registerCustomMimeTypeForFileExtension (mimeType, fileExtension);\r
+}\r
+\r
 } // namespace juce\r
index a6b8a974f195f88d3ddacaf4cb3945bcd9bb4e14..1fadc42a53e0f8c56ac732ac9b1bbcefcdf1a070 100644 (file)
 \r
 namespace juce\r
 {\r
+\r
 // This byte-code is generated from native/java/com/rmsl/juce/ComponentPeerView.java with min sdk version 16\r
 // See juce_core/native/java/README.txt on how to generate this byte-code.\r
-static const uint8 javaComponentPeerView[] =\r
-{ 31,139,8,8,217,126,216,97,0,3,74,97,118,97,68,101,120,66,121,116,101,67,111,100,101,46,100,101,120,0,165,155,11,124,212,213,149,199,207,189,255,255,204,36,147,215,100,18,146,64,18,50,9,175,16,72,102,8,111,19,148,183,6,18,64,18,16,18,171,76,146,127,146,\r
-  129,201,127,134,153,73,72,124,21,149,143,96,173,21,45,82,21,109,177,165,182,110,109,215,90,219,181,22,181,93,93,215,173,186,85,107,87,180,90,31,69,197,150,90,180,86,105,117,117,127,247,49,147,9,143,210,118,195,231,59,231,252,207,125,223,123,238,185,247,\r
-  63,33,221,214,144,59,48,115,54,125,253,172,186,247,86,249,42,166,141,253,112,218,236,231,195,83,47,91,120,183,99,205,99,123,255,208,184,125,22,81,148,136,134,214,207,242,146,254,57,56,147,168,146,41,251,60,240,129,73,180,4,242,121,7,81,9,228,241,12,162,\r
-  203,33,31,200,36,66,18,237,207,33,218,52,153,200,151,75,212,94,78,116,33,184,24,116,130,205,192,6,215,128,107,193,245,96,55,216,3,110,1,251,192,215,192,195,224,5,240,18,248,13,120,3,188,5,126,15,142,129,63,131,156,241,232,7,184,8,12,131,61,224,126,240,\r
-  60,248,12,140,173,32,170,7,231,130,207,129,65,112,19,120,8,60,7,142,130,137,62,162,101,96,8,220,3,14,131,194,74,162,6,208,11,246,130,23,64,69,21,198,2,46,7,119,130,159,129,195,192,152,64,84,14,2,160,13,92,2,110,0,247,129,199,193,155,224,47,160,122,34,\r
-  209,82,208,1,194,224,10,176,3,220,4,110,6,183,130,253,224,0,184,7,220,7,126,12,30,1,143,129,39,192,211,224,57,240,2,120,5,188,14,222,1,71,193,123,224,35,240,9,48,38,17,101,130,28,224,5,227,64,37,152,4,166,130,5,96,45,184,8,108,6,131,224,42,240,37,112,\r
-  27,184,11,220,7,30,6,79,130,151,192,49,112,28,56,176,174,121,160,6,204,6,243,192,74,208,10,58,64,23,8,131,56,216,14,174,7,119,128,123,192,15,193,65,240,34,120,21,188,1,222,1,89,83,136,138,64,57,152,6,230,129,117,32,14,174,0,55,128,187,192,15,193,35,224,\r
-  73,240,34,56,12,254,2,114,171,137,202,192,20,48,15,44,7,171,193,6,96,129,109,96,39,184,29,124,7,252,4,188,8,94,5,111,130,35,128,79,37,42,0,147,192,92,176,28,180,130,16,184,4,92,7,110,3,223,2,7,193,227,224,85,240,14,248,35,120,31,124,10,140,26,248,15,\r
-  152,0,102,129,115,64,11,184,0,92,12,182,128,1,176,27,236,3,7,192,67,224,41,240,75,240,6,56,2,142,129,227,224,99,192,166,17,185,65,33,168,2,53,32,0,230,128,38,112,17,136,130,171,193,126,240,3,240,56,120,21,188,13,62,4,206,233,40,15,42,64,29,152,11,22,\r
-  129,53,224,34,208,3,34,96,24,108,7,95,4,251,192,215,193,207,192,99,224,105,240,30,200,171,197,122,129,82,48,13,204,7,107,65,39,136,130,47,128,59,193,195,224,73,240,18,120,11,124,8,204,58,204,51,152,0,234,65,51,88,11,54,128,77,160,15,216,32,14,134,193,\r
-  213,224,26,112,61,216,11,110,7,223,5,15,128,159,131,23,193,155,224,8,248,61,248,35,248,19,248,8,124,12,62,3,78,196,36,132,40,202,2,69,160,152,84,220,26,11,198,129,82,80,6,16,82,8,97,131,16,22,8,97,128,176,237,9,91,156,176,125,9,219,138,224,254,4,119,\r
-  37,184,28,193,101,8,203,77,88,30,194,244,18,166,133,48,60,66,115,228,7,1,48,3,212,3,132,79,66,88,165,217,96,14,152,171,227,232,124,112,22,104,0,141,96,1,56,27,156,3,22,130,69,96,49,169,88,187,12,156,7,54,128,78,208,5,186,129,69,106,124,201,31,151,150,\r
-  247,151,170,49,51,253,236,214,186,176,139,121,224,218,158,173,245,131,176,231,165,213,229,213,115,246,152,182,231,106,123,158,78,75,234,99,180,238,209,243,42,234,47,208,250,83,186,108,73,90,157,98,174,159,47,85,186,152,227,151,117,158,201,105,245,76,\r
-  213,245,228,107,253,48,244,66,173,31,45,85,109,138,57,255,64,215,35,244,79,116,61,181,186,158,49,122,29,204,50,213,31,177,22,217,101,106,14,235,117,158,38,173,139,182,86,104,189,16,121,86,106,93,180,219,172,117,31,236,45,90,15,64,95,165,245,70,232,171,\r
-  181,126,30,244,53,90,111,131,126,190,214,47,132,222,170,245,238,52,123,56,77,79,64,95,167,245,203,210,236,187,210,244,221,105,250,45,105,117,238,79,179,127,27,122,155,214,239,77,179,31,40,29,209,197,156,175,213,186,152,207,100,61,15,164,229,23,243,185,\r
-  94,235,63,133,253,2,173,63,145,150,231,80,154,254,90,153,242,205,153,122,110,55,106,253,8,236,237,90,63,150,166,127,2,189,67,235,25,226,142,160,117,15,244,207,105,189,76,220,27,180,94,13,253,34,173,7,210,236,194,199,54,105,125,30,236,65,173,159,151,150,\r
-  191,173,92,248,57,163,97,82,50,135,137,125,63,137,226,164,228,191,73,201,232,65,45,15,106,249,144,150,15,107,249,136,206,255,115,18,177,194,71,110,166,100,1,19,113,99,38,253,23,9,89,65,89,76,196,16,149,94,161,211,43,144,82,196,132,207,23,209,86,225,79,\r
-  216,117,15,72,89,65,79,72,89,78,191,148,114,38,189,35,101,22,29,149,62,63,153,150,67,58,16,129,254,68,98,127,58,233,70,41,199,208,126,200,76,68,49,67,202,89,244,33,137,125,94,45,159,179,180,61,11,17,225,35,57,110,245,156,135,118,111,144,178,136,110,210,\r
-  207,183,106,121,167,152,127,157,46,228,110,41,77,186,89,63,239,147,210,160,219,73,237,211,59,180,252,170,148,140,238,210,242,91,36,246,37,167,189,82,78,165,111,146,216,131,147,100,251,5,136,120,191,149,114,62,29,150,178,148,222,38,177,95,107,105,64,203,\r
-  15,72,196,233,57,244,31,36,226,72,54,61,47,229,88,122,159,68,44,81,227,24,139,136,43,100,25,162,230,143,164,172,161,191,74,121,14,153,114,93,2,50,189,28,51,176,67,202,18,218,165,159,175,149,114,30,189,43,215,171,78,230,27,143,26,95,39,177,78,170,92,5,\r
-  236,61,90,246,74,153,71,125,82,142,37,7,83,210,41,215,115,178,204,239,195,10,133,164,244,211,102,41,23,209,22,41,11,40,172,101,191,148,11,201,150,114,44,13,105,121,185,148,115,233,74,41,43,233,58,41,189,116,189,148,57,244,37,41,157,180,71,251,205,94,\r
-  157,254,21,41,103,211,45,82,102,210,215,164,116,211,215,117,190,111,72,153,65,7,164,84,235,32,252,236,110,41,203,232,95,180,252,142,150,247,104,127,252,174,148,227,233,123,218,254,175,186,220,189,90,126,95,203,251,164,244,209,15,164,108,160,251,165,156,\r
-  67,143,105,249,184,148,19,232,5,41,171,232,144,150,47,106,249,146,78,255,181,126,126,89,203,87,164,204,165,223,72,57,133,94,149,114,58,189,38,229,217,244,134,148,202,143,124,218,143,196,243,155,122,255,188,37,165,242,43,145,255,136,148,141,116,76,202,\r
-  122,58,174,229,95,164,156,70,159,72,57,142,62,149,114,6,125,166,159,137,169,124,76,75,206,84,186,193,212,188,20,50,113,110,21,211,109,36,228,98,122,84,238,87,78,63,147,50,159,188,76,156,77,202,95,167,97,103,124,153,196,249,100,208,21,82,114,122,154,196,\r
-  25,85,72,255,78,226,190,48,86,251,171,218,83,201,51,19,175,88,116,33,98,220,21,250,208,26,175,237,226,204,19,49,93,164,39,32,239,208,233,21,186,252,180,180,242,59,144,126,175,78,247,145,58,87,197,153,120,143,46,191,7,242,144,78,23,119,129,169,208,3,245,\r
-  234,190,112,86,189,178,173,134,92,15,12,157,190,9,108,214,121,226,210,110,72,157,251,213,189,161,131,185,41,234,17,55,168,14,158,133,181,204,64,45,162,173,28,191,186,59,121,89,91,167,155,182,122,102,193,158,197,139,240,218,56,131,115,115,62,55,201,229,\r
-  201,167,182,206,44,218,234,171,160,24,118,191,200,215,214,165,242,26,148,101,110,93,51,135,22,15,184,249,124,254,135,207,108,143,24,143,203,83,253,182,169,219,159,224,87,119,152,42,204,104,212,115,153,28,173,104,91,244,187,214,175,238,96,167,107,219,\r
-  160,124,230,245,206,156,50,246,228,54,3,115,105,177,35,27,49,227,24,218,20,113,202,205,108,223,20,68,169,108,86,253,214,201,185,231,201,220,213,239,136,248,107,202,254,44,241,171,181,107,139,170,124,34,165,136,203,123,9,159,143,60,94,196,151,182,173,\r
-  238,244,116,206,118,176,155,93,119,109,115,206,199,200,16,215,143,25,232,175,24,227,106,191,136,247,152,89,111,14,198,184,13,54,47,93,232,201,150,119,180,12,60,137,177,110,240,171,179,182,192,89,72,85,60,27,249,196,44,180,197,115,168,109,102,46,217,158,\r
-  165,200,149,205,230,179,198,17,155,239,60,236,197,145,28,139,144,195,109,172,157,40,222,21,25,125,191,237,70,50,204,217,155,198,209,186,56,230,193,40,34,175,113,33,180,100,254,182,68,14,250,29,192,72,178,77,209,127,83,206,195,108,90,226,16,249,231,27,\r
-  46,154,187,201,65,222,2,81,70,180,85,140,56,103,123,138,196,200,78,104,163,250,191,197,90,10,159,187,218,175,238,116,29,222,92,61,206,42,204,97,212,39,246,82,135,7,20,228,201,49,51,249,143,232,203,126,245,253,67,212,35,110,123,185,41,251,190,148,189,\r
-  94,218,185,190,21,127,195,175,252,185,205,147,39,247,132,240,32,209,238,119,252,234,94,220,230,203,67,31,197,205,27,227,172,244,160,215,101,104,57,55,149,239,190,211,230,43,151,249,114,225,241,98,36,63,70,190,167,132,223,185,188,69,81,95,9,226,111,149,\r
-  153,133,222,56,209,171,142,61,69,120,170,160,104,160,150,246,100,118,236,41,192,83,57,158,38,203,167,66,212,187,16,107,157,109,142,115,68,81,47,86,16,122,133,89,132,114,249,84,102,58,96,75,32,190,187,205,121,230,231,168,194,45,158,241,158,74,237,183,\r
-  123,161,69,113,227,185,112,223,24,104,33,156,77,182,111,179,252,220,130,243,190,10,117,70,61,242,60,54,11,105,194,162,89,52,153,137,27,161,237,51,209,243,54,209,39,7,246,175,207,65,162,70,23,90,245,26,182,103,72,247,228,99,242,78,158,208,51,7,227,233,\r
-  204,40,166,150,12,167,203,91,92,150,145,37,53,59,16,167,54,103,182,49,207,40,36,47,247,78,156,176,116,46,121,29,91,61,131,152,135,108,103,139,211,116,120,199,120,165,180,3,151,210,151,77,225,105,194,187,197,168,84,239,247,80,245,157,57,102,245,7,224,\r
-  125,112,12,188,4,196,225,97,152,242,61,96,228,103,251,57,244,15,61,159,248,163,210,197,93,178,8,251,241,18,82,247,23,110,84,223,202,166,124,133,213,221,204,248,244,59,88,205,62,70,58,186,224,221,47,160,124,166,213,231,149,113,214,148,145,15,239,125,1,\r
-  237,99,129,213,84,105,228,98,207,59,100,188,155,27,80,49,54,186,174,143,42,151,184,165,63,39,203,44,77,166,5,22,163,76,182,244,193,100,90,75,42,237,236,84,154,75,222,254,16,135,117,218,160,179,77,70,6,81,167,67,239,123,43,160,246,76,235,66,111,90,124,\r
-  49,224,139,194,18,13,52,227,118,84,253,215,145,241,244,235,186,196,123,113,59,198,148,171,251,32,126,226,1,21,251,189,158,188,212,158,185,60,144,220,51,133,178,79,73,251,213,218,190,206,51,70,182,207,245,222,187,54,160,222,61,109,207,114,217,87,25,235,\r
-  80,159,151,170,63,53,116,59,55,4,212,57,146,43,203,169,55,211,175,164,217,156,58,126,127,245,12,99,91,161,199,150,204,255,173,51,228,95,153,154,11,213,143,123,79,209,143,7,78,97,123,36,205,102,234,182,30,15,168,239,11,188,76,124,163,208,17,224,164,164,\r
-  65,27,103,32,238,29,219,24,112,209,198,128,83,91,51,225,199,88,73,207,198,128,137,244,12,236,199,177,232,79,21,249,88,190,30,175,88,147,95,5,212,89,125,234,254,183,45,46,162,232,218,86,50,207,175,62,46,124,195,144,254,247,202,105,203,204,92,246,217,103,\r
-  114,220,11,23,144,25,20,101,220,104,71,156,213,191,11,168,239,57,218,182,231,99,157,196,41,229,198,73,55,142,90,175,68,20,241,228,98,215,187,177,251,189,66,154,182,167,64,72,135,141,53,204,164,44,167,107,251,96,70,147,246,17,177,166,110,180,37,124,244,\r
-  163,128,250,174,195,235,105,141,161,39,226,140,101,56,99,153,58,233,166,139,87,62,18,41,54,206,45,85,95,150,144,78,215,86,182,99,208,217,130,249,173,254,67,36,48,150,118,102,226,228,59,98,123,206,194,8,171,197,69,143,171,113,38,191,191,17,178,64,147,\r
-  173,207,218,49,51,212,123,159,151,90,175,66,219,78,217,182,115,62,51,208,242,252,204,76,180,137,158,227,4,247,86,213,87,186,40,178,112,28,221,242,32,90,121,223,246,184,97,207,102,243,152,184,89,40,221,246,13,11,191,117,136,154,68,31,179,68,31,175,100,\r
-  123,84,31,189,158,234,23,212,220,139,245,154,57,67,125,239,48,122,238,213,136,133,77,140,213,73,110,30,93,187,10,171,134,178,127,38,189,163,137,22,205,24,241,169,76,29,59,86,207,80,107,25,217,80,74,109,131,233,181,206,67,155,202,135,99,240,97,81,38,79,\r
-  175,229,38,36,151,161,162,214,103,145,219,16,35,103,134,156,117,150,199,108,79,14,234,119,103,138,181,203,165,44,215,175,110,252,140,166,177,15,165,215,86,191,215,250,156,23,210,246,229,227,140,21,235,44,98,129,88,151,2,33,157,174,103,7,51,214,136,17,\r
-  231,87,191,124,230,156,107,85,206,255,60,115,206,243,145,211,246,136,211,210,157,229,205,159,91,90,67,222,202,9,101,179,113,18,44,193,253,216,59,110,246,131,149,36,106,17,117,124,79,212,225,43,20,146,121,29,75,29,217,142,171,214,61,62,198,246,141,81,\r
-  150,162,165,206,108,231,85,61,143,23,37,235,61,228,118,179,234,215,208,143,171,113,83,199,165,254,135,55,190,238,102,25,243,221,37,244,247,142,96,42,245,124,150,222,159,127,166,39,162,166,234,95,255,227,61,88,163,123,48,233,255,221,131,53,178,7,88,102,\r
-  166,190,29,20,190,37,226,144,95,75,17,191,196,187,91,92,250,30,151,119,150,23,102,168,239,50,209,71,156,251,46,202,230,227,140,255,37,111,225,132,165,56,247,29,157,78,156,251,242,12,143,83,189,41,238,145,46,244,59,7,251,31,124,226,245,78,168,194,169,\r
-  111,136,83,63,3,39,123,139,201,13,113,218,111,229,213,239,230,240,234,163,224,119,224,136,240,247,124,244,173,84,238,93,68,61,62,189,168,166,196,168,174,158,50,189,174,38,45,222,26,245,35,123,195,208,214,172,122,117,7,158,199,93,36,102,196,70,142,92,\r
-  242,46,172,254,88,140,79,197,228,194,122,21,7,196,29,74,220,118,199,241,159,202,59,84,37,90,171,192,251,219,60,68,15,219,115,9,118,168,155,45,96,5,152,109,59,48,137,2,24,241,185,50,191,29,152,72,30,179,109,70,1,110,182,117,178,254,100,138,151,219,129,\r
-  9,228,225,42,205,47,230,247,125,146,191,239,18,63,201,239,92,197,123,206,116,216,102,37,191,60,213,63,11,79,120,94,115,194,179,40,95,72,234,236,205,71,239,152,182,9,124,90,102,232,116,175,62,103,199,105,123,133,150,92,227,211,243,53,141,230,74,123,173,\r
-  182,215,34,58,43,201,100,60,101,250,159,131,70,206,116,174,125,35,121,150,155,41,157,105,187,43,245,93,50,199,76,179,84,126,33,115,82,101,132,116,234,52,39,242,113,109,115,105,153,169,101,242,187,232,92,217,43,210,247,11,49,198,153,122,44,62,105,159,\r
-  169,125,120,102,170,215,170,252,44,45,103,235,114,201,126,10,153,163,219,23,122,94,42,61,47,109,76,57,169,177,22,167,250,161,234,246,232,246,124,169,156,106,92,62,157,155,145,122,223,102,213,132,247,41,103,99,200,14,37,206,38,126,118,3,21,45,137,244,\r
-  71,35,182,101,39,214,88,86,108,125,200,218,86,183,57,56,24,36,182,156,248,242,38,98,77,196,155,166,2,168,43,136,175,104,166,242,21,3,93,214,162,174,46,43,30,15,117,134,194,161,196,240,170,72,183,181,38,22,25,12,117,91,49,42,94,105,13,119,70,130,177,238,\r
-  165,161,120,127,40,30,111,14,197,19,150,141,4,214,76,188,25,181,53,163,154,230,102,50,154,241,128,143,21,226,163,153,138,154,131,118,119,44,18,234,246,7,163,81,255,162,174,68,104,16,53,55,208,172,209,246,104,52,28,234,10,38,66,17,123,98,50,79,115,168,\r
-  199,234,26,238,10,91,75,130,225,112,103,176,107,75,188,129,198,158,174,84,122,82,87,196,70,207,18,254,37,66,14,37,210,147,122,99,193,104,95,168,43,238,95,18,180,7,131,168,112,252,41,146,34,225,72,108,121,40,156,176,98,167,79,111,9,38,98,161,161,6,154,\r
-  250,55,211,71,85,85,114,114,214,53,193,144,141,254,21,159,156,178,214,234,66,66,65,42,33,18,247,47,30,176,187,195,86,3,21,166,27,155,22,135,236,110,81,251,72,29,131,88,106,63,22,107,217,160,37,42,31,55,58,161,37,34,166,75,167,77,29,157,38,156,100,226,\r
-  106,123,121,164,107,32,190,164,47,104,247,90,201,69,78,239,74,42,107,250,144,82,198,115,99,145,129,104,3,205,57,57,165,45,102,89,171,59,227,86,108,208,138,161,149,115,195,145,206,96,184,57,56,28,25,72,140,52,83,241,183,203,53,208,140,209,25,130,233,254,\r
-  234,31,229,189,45,65,59,216,43,138,212,255,221,69,132,195,55,217,61,145,147,250,127,134,50,201,77,210,64,117,163,203,133,236,232,64,162,223,74,244,69,186,253,139,131,113,84,142,103,248,165,141,229,149,94,59,233,244,249,151,117,135,18,145,152,234,78,205,\r
-  233,179,157,84,101,237,25,242,182,72,61,53,59,231,52,119,69,250,253,177,254,120,216,191,25,1,192,127,82,216,152,248,55,227,66,3,45,63,99,5,167,137,28,19,71,175,236,252,127,182,158,6,170,60,83,209,6,170,106,238,14,134,7,67,91,252,65,219,142,36,100,204,\r
-  240,47,179,187,194,145,120,200,238,93,18,14,198,101,48,56,57,79,19,38,54,166,211,43,79,145,222,98,245,119,234,12,22,178,148,159,34,75,107,168,215,14,38,6,98,150,216,48,34,6,251,195,216,91,126,236,176,88,171,181,117,192,178,187,144,146,159,158,162,154,\r
-  171,74,51,53,133,195,86,111,48,172,150,97,217,80,151,21,85,139,61,241,20,121,98,189,3,253,24,123,90,174,130,244,92,8,138,189,106,210,70,140,171,34,173,3,93,125,202,51,210,202,121,211,178,172,238,220,44,99,82,121,154,173,213,234,26,136,193,33,78,83,164,\r
-  21,49,208,238,21,30,57,98,139,89,61,97,212,131,110,12,70,84,232,110,11,198,122,173,244,222,142,59,69,118,213,181,6,26,163,210,6,18,161,176,127,81,44,22,28,22,78,208,64,121,105,102,97,33,207,9,134,6,50,219,54,174,89,70,217,233,62,71,108,61,241,245,77,\r
-  228,88,223,132,31,168,43,200,185,126,69,211,242,229,120,155,135,20,9,43,68,2,30,196,193,182,126,69,59,242,8,69,28,110,235,165,169,185,29,169,205,237,56,250,214,183,163,112,187,172,136,181,147,209,46,202,225,163,89,168,205,228,104,95,33,116,19,2,199,101,\r
-  187,176,226,152,116,182,55,75,179,67,72,216,59,112,54,119,52,145,183,227,100,103,40,232,56,197,90,184,85,92,154,24,8,4,82,250,140,52,189,62,77,159,153,166,207,74,211,103,167,233,115,210,244,185,105,250,60,232,89,74,95,30,14,246,198,41,103,84,64,164,194,\r
-  224,41,2,47,57,131,50,34,137,146,66,54,7,59,173,48,101,4,245,241,78,99,131,221,221,167,62,6,40,51,168,125,56,78,172,147,242,197,225,191,120,32,145,136,216,107,98,104,198,234,38,103,103,4,143,253,144,242,80,36,103,151,60,207,201,213,37,143,173,110,114,\r
-  224,222,16,140,81,86,151,8,85,17,156,178,139,18,226,33,117,50,83,174,124,104,139,5,237,120,79,36,214,79,57,226,214,128,227,56,46,115,163,34,117,121,64,69,145,1,60,151,118,197,172,96,226,228,48,40,194,51,153,221,161,158,30,98,22,57,44,113,174,146,175,\r
-  7,135,242,41,179,198,23,15,183,137,90,51,69,14,121,206,146,163,71,138,236,158,145,83,183,155,178,228,147,136,92,77,221,84,138,237,49,170,182,229,105,137,101,39,38,142,186,180,101,202,84,185,10,121,41,181,37,24,223,130,54,198,8,195,200,13,74,223,150,40,\r
-  7,102,17,154,176,78,86,44,78,25,226,81,184,32,185,133,166,51,101,139,29,43,198,218,22,234,183,100,43,231,89,161,222,190,4,21,64,149,167,76,122,31,133,177,89,239,246,213,118,43,166,210,178,101,21,216,213,193,86,68,73,85,133,218,227,178,163,114,17,16,86,\r
-  229,220,103,143,24,80,153,11,79,107,131,219,54,36,149,141,148,37,148,72,36,33,90,35,15,30,90,135,225,71,253,173,216,227,161,46,139,114,97,89,103,135,132,39,136,113,201,222,156,120,175,144,163,94,31,74,57,180,40,115,1,150,40,178,173,45,178,5,157,45,75,\r
-  61,203,76,97,11,71,80,52,28,28,94,30,11,98,252,38,82,55,200,207,141,196,250,168,4,139,8,167,28,181,42,231,69,68,43,121,58,37,26,93,19,28,16,126,236,73,25,214,90,113,120,124,202,178,56,229,242,148,163,44,56,252,150,70,182,97,55,165,30,215,69,169,48,245,\r
-  32,15,198,243,66,221,221,232,173,110,166,37,130,54,100,153,81,134,88,176,55,89,167,52,160,26,93,167,188,142,82,129,126,176,98,98,99,104,239,201,232,11,198,149,191,22,247,193,179,90,35,61,122,153,99,145,126,53,49,200,130,210,210,187,205,190,8,66,48,11,\r
-  145,27,222,177,90,70,245,56,25,161,254,126,202,19,239,39,161,96,120,73,48,26,111,193,130,80,142,54,180,90,225,101,118,119,42,29,143,240,139,24,54,138,188,190,180,13,71,45,202,150,234,197,234,42,67,25,104,108,125,48,60,128,189,31,194,81,178,197,66,99,\r
-  241,38,59,158,8,226,56,69,106,124,117,52,136,179,149,198,134,226,109,17,156,109,203,134,162,216,239,210,5,151,217,65,172,96,55,234,142,235,213,36,215,22,107,120,137,232,79,241,150,211,188,229,228,36,19,90,251,196,140,58,194,50,154,229,192,7,172,152,232,\r
-  222,42,220,55,200,12,91,61,9,114,134,45,187,55,209,71,78,221,85,102,147,105,11,63,113,217,214,182,85,66,201,176,147,161,35,219,78,223,174,206,72,167,136,65,100,70,194,221,125,242,115,27,229,71,236,228,27,209,18,25,131,176,159,70,76,75,173,120,34,22,25,\r
-  22,142,51,98,212,206,149,86,50,233,93,165,35,166,214,224,160,149,156,47,181,7,211,242,203,201,31,93,69,107,34,18,141,194,84,140,80,33,251,113,194,197,19,157,183,225,91,219,40,39,146,254,6,65,185,145,81,49,158,178,35,182,220,12,50,124,80,102,196,78,58,\r
-  118,142,84,91,6,194,137,80,84,44,137,124,132,115,102,136,163,67,22,69,142,214,208,37,86,50,72,162,38,181,180,178,38,103,68,45,184,75,201,139,81,110,0,81,63,129,24,230,136,74,199,118,71,131,49,228,148,97,34,39,58,202,189,29,81,25,245,203,163,145,232,64,\r
-  248,180,113,158,197,200,21,83,239,164,84,21,179,122,133,111,196,78,255,186,74,101,49,171,31,67,85,195,95,109,159,112,200,57,98,50,98,26,113,43,65,185,113,17,91,83,47,139,148,141,103,57,137,194,83,169,56,253,169,73,13,90,238,30,81,44,237,78,47,139,53,\r
-  39,61,146,74,240,116,202,183,57,26,19,79,6,201,117,161,180,168,87,122,74,179,184,76,7,113,122,198,85,216,148,14,156,19,31,21,46,221,201,199,176,234,211,5,161,112,120,85,36,33,221,33,59,142,13,147,12,80,40,136,167,84,244,64,102,225,104,170,95,184,42,34,\r
-  25,94,54,242,88,18,87,189,105,26,105,75,143,212,148,199,144,153,232,11,197,201,41,62,39,6,180,156,1,171,56,148,12,212,4,85,76,68,198,64,162,103,158,140,253,108,144,28,131,50,106,184,164,88,221,67,166,120,75,162,60,241,153,238,92,153,194,208,22,89,23,\r
-  183,200,51,120,210,105,49,24,138,37,6,130,97,125,190,185,7,71,166,130,109,35,54,68,124,40,0,102,128,122,48,19,204,34,54,76,223,52,57,237,229,174,220,246,90,186,199,100,183,112,87,57,207,122,150,15,149,111,54,232,151,172,228,141,149,244,144,201,175,229,\r
-  176,231,210,163,38,187,142,185,202,159,228,151,148,191,111,208,245,172,166,246,38,7,209,115,166,113,11,143,111,115,229,62,90,65,191,229,140,80,85,35,253,142,147,107,122,135,193,223,103,57,215,26,236,93,86,80,55,244,145,65,215,48,190,185,145,229,231,135,\r
-  26,121,188,220,65,141,44,203,137,242,92,117,128,207,217,200,87,110,171,165,95,112,118,187,104,237,68,121,8,85,230,222,79,175,40,209,104,92,205,126,207,126,204,92,211,249,179,212,192,63,101,219,248,51,108,219,16,127,227,210,215,118,49,238,112,47,170,109,\r
-  172,107,108,60,187,195,160,237,204,125,153,193,174,100,179,27,239,170,52,140,95,176,0,43,30,19,24,111,240,167,24,103,249,197,14,206,207,71,87,28,204,97,56,221,124,218,1,135,219,73,78,230,228,78,163,166,134,15,78,119,240,26,30,159,78,115,85,23,230,242,\r
-  219,249,29,82,49,133,242,85,254,181,209,214,148,226,72,38,239,23,143,215,137,46,127,161,140,6,33,86,210,97,131,239,227,119,10,251,235,38,12,180,75,76,25,189,100,136,207,47,152,124,224,82,200,29,38,27,128,120,215,16,2,37,111,150,207,215,149,209,167,134,\r
-  202,176,91,101,56,46,51,208,141,6,59,138,133,89,185,178,182,125,101,123,29,125,158,93,38,75,221,107,240,27,249,143,24,10,150,214,210,219,140,237,130,186,139,21,229,249,104,15,231,79,136,199,242,157,124,76,57,239,47,231,121,13,117,43,45,62,176,226,66,\r
-  62,188,130,30,228,198,19,108,135,76,231,249,215,240,88,249,222,142,205,187,12,199,110,206,253,214,57,116,175,46,155,187,211,87,182,151,238,54,28,151,63,205,190,196,63,100,151,160,35,251,13,243,54,126,55,123,129,253,15,210,23,236,108,167,91,84,171,59,\r
-  249,19,84,206,31,252,124,249,74,35,51,206,155,13,215,245,220,224,143,210,70,190,112,58,43,200,11,40,60,205,70,214,51,140,47,104,52,178,143,177,57,11,24,51,220,15,50,94,203,202,114,206,113,184,29,217,51,28,89,155,157,238,58,86,80,196,47,109,104,116,102,\r
-  47,96,229,99,132,125,180,145,47,103,229,185,244,136,193,110,197,12,251,12,182,139,7,152,183,136,103,79,199,40,43,12,218,201,106,199,59,72,42,211,38,56,232,245,64,13,253,196,96,207,161,139,244,170,193,134,92,185,161,50,58,206,216,13,40,252,152,65,7,89,\r
-  121,221,230,149,67,155,198,238,36,94,201,110,228,37,62,94,197,35,166,247,25,86,156,195,39,194,80,230,42,102,197,11,139,51,139,151,22,243,226,154,98,83,229,170,144,185,224,143,197,231,166,242,231,242,9,34,63,43,25,175,20,94,82,94,82,65,156,153,238,221,\r
-  62,230,157,124,229,118,243,80,217,20,118,188,140,177,67,229,140,125,0,142,141,71,50,203,230,108,183,111,218,246,237,230,193,138,233,236,181,10,50,156,148,43,74,48,111,45,202,28,168,100,187,124,207,139,143,163,226,99,71,21,227,183,131,199,170,200,89,82,\r
-  154,239,133,135,123,213,191,153,200,124,180,10,89,30,152,140,143,103,196,199,17,241,177,99,10,62,246,139,143,131,83,204,171,56,49,32,164,75,235,127,47,133,192,13,206,98,135,166,96,201,171,25,59,80,109,176,7,170,139,216,51,208,143,128,47,78,101,108,63,\r
-  184,31,28,6,123,106,24,251,54,56,8,158,1,7,166,97,232,224,139,211,25,123,13,188,92,203,216,243,117,204,220,237,103,230,1,63,210,252,14,182,127,22,99,247,204,230,236,167,224,240,108,79,218,239,7,146,50,249,119,57,226,251,234,228,223,230,136,239,177,147,\r
-  127,159,147,252,93,169,248,27,29,241,29,118,242,239,116,156,52,242,183,58,134,71,127,191,157,139,58,125,234,247,66,27,160,59,125,42,143,248,255,103,204,163,236,226,255,156,113,159,106,87,252,109,143,161,243,139,255,247,101,250,212,239,37,166,214,171,\r
-  95,84,136,178,242,255,173,121,84,95,197,223,17,253,31,67,245,215,66,128,52,0,0,0,0 };\r
+static const uint8 javaComponentPeerView[]\r
+{\r
+  0x1f, 0x8b, 0x08, 0x08, 0x16, 0x5e, 0x87, 0x63, 0x00, 0x03, 0x63, 0x6c,\r
+  0x61, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x64, 0x65, 0x78, 0x00, 0xad, 0x7c,\r
+  0x0b, 0x7c, 0x94, 0xd5, 0xb5, 0xef, 0xda, 0xdf, 0x3c, 0x33, 0x79, 0xcd,\r
+  0x4c, 0x02, 0xe1, 0xcd, 0x24, 0xa0, 0xe4, 0x9d, 0x21, 0xbc, 0x12, 0x12,\r
+  0x20, 0x21, 0x04, 0x4c, 0x08, 0x10, 0xc8, 0x10, 0x24, 0xa1, 0xca, 0x90,\r
+  0x0c, 0x64, 0x64, 0x98, 0x19, 0x66, 0x26, 0x01, 0x7c, 0x15, 0x29, 0x0a,\r
+  0xf5, 0x51, 0xb1, 0xda, 0x4a, 0xd5, 0xf6, 0x58, 0xaf, 0x2f, 0x3c, 0xea,\r
+  0x41, 0xc5, 0xfa, 0xa8, 0xb6, 0xd6, 0xaa, 0xd5, 0xa3, 0xa7, 0xea, 0x39,\r
+  0xf6, 0x96, 0xdb, 0x63, 0xab, 0x1e, 0xb5, 0xad, 0xad, 0x57, 0xed, 0xa9,\r
+  0xad, 0x7a, 0x8f, 0x3d, 0xde, 0xff, 0xda, 0x7b, 0xcf, 0xe4, 0x1b, 0x12,\r
+  0xd4, 0xde, 0xdf, 0x4d, 0xf8, 0x7f, 0x6b, 0xed, 0xb5, 0xd6, 0x7e, 0xaf,\r
+  0xbd, 0xf6, 0xde, 0xdf, 0x84, 0x19, 0x0c, 0xed, 0x75, 0xf9, 0xe7, 0x2d,\r
+  0xa0, 0xee, 0xef, 0xbf, 0xfb, 0xe4, 0x77, 0xef, 0x38, 0xfe, 0xef, 0xe7,\r
+  0xdc, 0x31, 0xe9, 0xf1, 0x87, 0x7e, 0x3c, 0xf2, 0xe2, 0x88, 0x38, 0x74,\r
+  0xe6, 0xbc, 0x07, 0xde, 0xff, 0xaa, 0xbf, 0x8b, 0x28, 0x4e, 0x44, 0x7b,\r
+  0x7b, 0xe7, 0x7b, 0x49, 0xff, 0x44, 0x56, 0x13, 0x85, 0x84, 0x92, 0xaf,\r
+  0x04, 0xac, 0x76, 0xa2, 0x21, 0xd0, 0x69, 0x0e, 0xa2, 0x59, 0xa0, 0x9f,\r
+  0xe6, 0x12, 0xfd, 0x1c, 0xb4, 0x38, 0x9f, 0x08, 0x22, 0x3a, 0x58, 0x44,\r
+  0xf4, 0xc2, 0x22, 0xa2, 0xc1, 0x62, 0x22, 0x5f, 0x2d, 0x51, 0x19, 0x70,\r
+  0x06, 0x50, 0x0e, 0x54, 0x01, 0xb5, 0x40, 0x3d, 0xb0, 0x00, 0x58, 0x02,\r
+  0xb4, 0x02, 0xab, 0x80, 0x75, 0xc0, 0x39, 0xc0, 0x08, 0x70, 0x00, 0xb8,\r
+  0x14, 0xf8, 0x3a, 0x70, 0x25, 0x70, 0x04, 0xb8, 0x0e, 0xf8, 0x0e, 0xf0,\r
+  0x5d, 0xe0, 0x16, 0xe0, 0x76, 0xe0, 0x18, 0x70, 0x0f, 0x70, 0x1f, 0xf0,\r
+  0x12, 0xf0, 0x0e, 0xf0, 0x2e, 0xf0, 0x01, 0xf0, 0x17, 0xe0, 0x13, 0xe0,\r
+  0x33, 0xc0, 0x52, 0x47, 0xe4, 0x04, 0xf2, 0x01, 0x2f, 0x50, 0x09, 0x6c,\r
+  0x05, 0x2e, 0x00, 0xbe, 0x0d, 0xdc, 0x07, 0xbc, 0x0c, 0xfc, 0x09, 0x98,\r
+  0xe6, 0x27, 0x5a, 0x08, 0x74, 0x03, 0x61, 0xe0, 0x52, 0xe0, 0x06, 0xe0,\r
+  0x38, 0xf0, 0x1c, 0xf0, 0x26, 0xf0, 0x19, 0x30, 0x79, 0x2e, 0x51, 0x0b,\r
+  0xb0, 0x05, 0xd8, 0x0d, 0x5c, 0x06, 0xdc, 0x0f, 0xbc, 0x04, 0xbc, 0x03,\r
+  0xd8, 0xea, 0x89, 0xfc, 0x40, 0x3b, 0x70, 0x2e, 0x70, 0x3d, 0xf0, 0x30,\r
+  0xf0, 0x47, 0x60, 0xe6, 0x3c, 0xa2, 0x4d, 0xc0, 0x21, 0xe0, 0x5e, 0xe0,\r
+  0x57, 0x40, 0xce, 0x7c, 0xa2, 0xc5, 0xc0, 0x10, 0x70, 0x0c, 0xf8, 0x13,\r
+  0x50, 0xbd, 0x00, 0x79, 0x81, 0x03, 0xc0, 0xed, 0xc0, 0x33, 0xc0, 0x3b,\r
+  0x80, 0x73, 0x21, 0xc6, 0x15, 0x58, 0x00, 0x6c, 0x06, 0xbe, 0x0a, 0x5c,\r
+  0x07, 0x3c, 0x04, 0x3c, 0x0f, 0xfc, 0x01, 0xf8, 0x6f, 0xa0, 0x06, 0xf3,\r
+  0xd0, 0x01, 0x6c, 0x05, 0x12, 0xc0, 0x41, 0xe0, 0x2a, 0xe0, 0x5a, 0xe0,\r
+  0x56, 0xe0, 0x7e, 0xe0, 0x41, 0xe0, 0x11, 0xe0, 0x47, 0xc0, 0x53, 0xc0,\r
+  0xf3, 0xc0, 0x8b, 0xc0, 0x2f, 0x81, 0x5f, 0x03, 0x6f, 0x01, 0xef, 0x00,\r
+  0xef, 0x01, 0x1f, 0x02, 0x9f, 0x00, 0x7f, 0x03, 0x8c, 0x06, 0xb4, 0x03,\r
+  0x28, 0x04, 0x8a, 0x81, 0xc9, 0x80, 0x0f, 0xa8, 0x00, 0xea, 0x80, 0xf9,\r
+  0xc0, 0x62, 0xa0, 0x05, 0x58, 0x01, 0x74, 0x01, 0xeb, 0x80, 0x00, 0xd0,\r
+  0x07, 0x9c, 0x0b, 0x0c, 0x00, 0xe7, 0x01, 0x71, 0x20, 0x05, 0xec, 0x03,\r
+  0x2e, 0x01, 0x0e, 0x03, 0x57, 0x02, 0x47, 0x80, 0x5b, 0x81, 0x47, 0x80,\r
+  0xa7, 0x81, 0x97, 0x81, 0xdf, 0x00, 0x7f, 0x04, 0x3e, 0x06, 0x6c, 0x8d,\r
+  0x98, 0x4f, 0x60, 0x26, 0x50, 0x0d, 0x34, 0x02, 0x2b, 0x81, 0x1e, 0xe0,\r
+  0x5c, 0x60, 0x27, 0xb0, 0x07, 0xf8, 0x1a, 0x70, 0x35, 0x70, 0x23, 0x70,\r
+  0x07, 0xf0, 0x00, 0xf0, 0x04, 0xf0, 0x22, 0xf0, 0x36, 0xf0, 0x9f, 0xc0,\r
+  0x47, 0x5c, 0xd6, 0x62, 0xa2, 0xd9, 0xc0, 0x22, 0xa0, 0x13, 0xd8, 0x00,\r
+  0xf4, 0x01, 0x11, 0xe0, 0x02, 0xe0, 0x00, 0x70, 0x2d, 0x70, 0x37, 0xf0,\r
+  0x08, 0xf0, 0x1c, 0x70, 0x12, 0x78, 0x0f, 0xc8, 0x6d, 0xc2, 0x38, 0x00,\r
+  0x33, 0x80, 0x72, 0xa0, 0x13, 0xd8, 0x08, 0x0c, 0x00, 0xfb, 0x81, 0xef,\r
+  0x01, 0xc7, 0x80, 0x47, 0x81, 0x97, 0x81, 0x37, 0x81, 0x4f, 0x00, 0x67,\r
+  0x33, 0xea, 0x05, 0xe6, 0x00, 0x4b, 0x81, 0x4e, 0x60, 0x13, 0x10, 0x02,\r
+  0xf6, 0x03, 0xb7, 0x00, 0xf7, 0x00, 0xcf, 0x02, 0x6f, 0x00, 0x7f, 0x05,\r
+  0xf2, 0x97, 0x60, 0xee, 0x81, 0xe5, 0x40, 0x0f, 0x30, 0x04, 0x8c, 0x00,\r
+  0x97, 0x00, 0xdf, 0x04, 0x6e, 0x06, 0x8e, 0x01, 0xf7, 0x03, 0x3f, 0x06,\r
+  0x5e, 0x02, 0xde, 0x04, 0xfe, 0x02, 0xd8, 0x96, 0x12, 0x95, 0x00, 0xd5,\r
+  0x40, 0x33, 0xb0, 0x1e, 0xd8, 0x0a, 0xc4, 0x81, 0x6f, 0x00, 0xd7, 0x01,\r
+  0x37, 0x00, 0x27, 0x80, 0xa7, 0x81, 0x5f, 0x02, 0xef, 0x00, 0x1f, 0x03,\r
+  0x8e, 0x65, 0xe8, 0x23, 0x50, 0x09, 0x34, 0x01, 0x5d, 0x40, 0x3f, 0x30,\r
+  0x04, 0x5c, 0x04, 0x5c, 0x01, 0xdc, 0x0a, 0xdc, 0x0b, 0x9c, 0x00, 0x9e,\r
+  0x00, 0x5e, 0x06, 0x5e, 0x07, 0xfe, 0x04, 0x7c, 0x0a, 0xb8, 0x5a, 0x88,\r
+  0xa6, 0x03, 0x73, 0x80, 0x3a, 0xa0, 0x09, 0x68, 0x07, 0xce, 0x06, 0x92,\r
+  0xc0, 0xc5, 0xc0, 0xf5, 0xc0, 0xed, 0xc0, 0x3d, 0xc0, 0x83, 0xc0, 0x0f,\r
+  0x81, 0xe7, 0x80, 0x97, 0x81, 0xb7, 0x81, 0x8f, 0x81, 0xfc, 0x56, 0xcc,\r
+  0x3b, 0x50, 0x0f, 0xac, 0x03, 0xb6, 0x01, 0xc3, 0xc0, 0x37, 0x80, 0x6f,\r
+  0x03, 0xb7, 0x01, 0x0f, 0x02, 0x3f, 0x05, 0x7e, 0x0e, 0xfc, 0x1a, 0xf8,\r
+  0x2d, 0xf0, 0x01, 0xf0, 0x19, 0x90, 0xb7, 0x9c, 0x68, 0x2a, 0x50, 0x09,\r
+  0x34, 0x02, 0xab, 0x80, 0x75, 0x40, 0x2f, 0x10, 0x02, 0x0e, 0x02, 0xd7,\r
+  0x03, 0x37, 0x03, 0x4f, 0x01, 0xff, 0x01, 0xbc, 0x07, 0x7c, 0x0a, 0x88,\r
+  0x36, 0x22, 0x0f, 0x30, 0x13, 0x68, 0x00, 0xd6, 0x02, 0x5b, 0x80, 0x11,\r
+  0xe0, 0x20, 0x70, 0x15, 0x70, 0x2b, 0xf0, 0x13, 0xe0, 0x57, 0xc0, 0xef,\r
+  0x80, 0xbf, 0x02, 0xc6, 0x0a, 0xcc, 0x35, 0xe0, 0x03, 0xea, 0x80, 0x65,\r
+  0xc0, 0x5a, 0xa0, 0x1f, 0xd8, 0x0e, 0x44, 0x81, 0xab, 0x81, 0x13, 0xc0,\r
+  0x6f, 0x00, 0x7b, 0x3b, 0xd1, 0x99, 0x40, 0x3b, 0xb0, 0x1d, 0x38, 0x0c,\r
+  0xdc, 0x05, 0xbc, 0x08, 0x7c, 0x04, 0x7c, 0x06, 0x38, 0x10, 0x94, 0x3d,\r
+  0xc0, 0x44, 0xa0, 0x11, 0x18, 0x04, 0x0e, 0x02, 0x77, 0x00, 0xf7, 0x02,\r
+  0x0f, 0x01, 0x8f, 0x03, 0x3f, 0x07, 0x5e, 0x07, 0x0a, 0x10, 0xa3, 0xdd,\r
+  0x40, 0x09, 0x70, 0x06, 0x70, 0x26, 0x30, 0x07, 0x28, 0x07, 0x2a, 0x80,\r
+  0x4a, 0xa0, 0x0a, 0xa8, 0x06, 0x6a, 0x00, 0x84, 0x4f, 0x42, 0x58, 0x24,\r
+  0x84, 0x3c, 0x42, 0x58, 0x23, 0x84, 0x2f, 0x42, 0xb8, 0x22, 0x84, 0x27,\r
+  0x42, 0x28, 0x22, 0x84, 0x19, 0x42, 0x38, 0x20, 0x2c, 0x47, 0xc2, 0x12,\r
+  0x22, 0xb8, 0x34, 0xc1, 0x45, 0x09, 0xae, 0x46, 0x70, 0x19, 0xc2, 0x94,\r
+  0x13, 0xa6, 0x8b, 0x30, 0xe4, 0x84, 0xa1, 0x23, 0x0c, 0x03, 0xa1, 0x6b,\r
+  0xd4, 0xae, 0xf7, 0x93, 0x55, 0xc0, 0x59, 0x40, 0x07, 0xd0, 0x09, 0x60,\r
+  0xbb, 0x21, 0x6c, 0x43, 0xb4, 0x06, 0x58, 0x0b, 0xac, 0x03, 0xba, 0x81,\r
+  0xf5, 0xc0, 0x06, 0xa0, 0x07, 0x08, 0x00, 0x1b, 0x81, 0x5e, 0x60, 0x13,\r
+  0x70, 0x36, 0xb0, 0x19, 0xe8, 0x03, 0xfa, 0x81, 0x2d, 0xc0, 0x57, 0x80,\r
+  0x73, 0x80, 0x73, 0x81, 0xad, 0x40, 0x10, 0xd8, 0x46, 0x6a, 0xef, 0xfa,\r
+  0x1a, 0xf0, 0x0d, 0xe0, 0x6a, 0xe0, 0x08, 0x70, 0x0d, 0xa9, 0x71, 0x49,\r
+  0xff, 0x14, 0x6a, 0x7a, 0xa2, 0x4a, 0x8d, 0x95, 0xd0, 0x69, 0xaf, 0xe6,\r
+  0x59, 0x5e, 0xa4, 0xf9, 0xc7, 0xc0, 0x17, 0x6b, 0xfe, 0x29, 0xf0, 0x13,\r
+  0x34, 0xff, 0x02, 0xf8, 0x89, 0x9a, 0x7f, 0xc5, 0xc4, 0xbf, 0x6a, 0xe2,\r
+  0xdf, 0xaa, 0x52, 0xf3, 0x60, 0xe8, 0xf2, 0x27, 0x69, 0x9e, 0xcb, 0x99,\r
+  0xac, 0xf9, 0x77, 0xc1, 0x4f, 0x03, 0xb5, 0x6b, 0x9b, 0x52, 0xc0, 0x09,\r
+  0x7c, 0xa8, 0xe5, 0x6e, 0x2d, 0x67, 0xde, 0x63, 0xe2, 0x27, 0x9b, 0xf8,\r
+  0xe9, 0x26, 0xde, 0xa7, 0x79, 0x96, 0x95, 0xe9, 0xbe, 0x94, 0x69, 0xfe,\r
+  0x53, 0x5d, 0xe6, 0x2c, 0x53, 0x5d, 0xec, 0x1f, 0xd6, 0x6a, 0x25, 0x9f,\r
+  0xa3, 0xe5, 0x33, 0x49, 0xf9, 0x06, 0xb7, 0x93, 0x6d, 0xd8, 0x47, 0xf2,\r
+  0x60, 0x33, 0x83, 0x94, 0x6f, 0x3c, 0xa6, 0xcb, 0x99, 0x6f, 0xaa, 0x6b,\r
+  0x91, 0xae, 0x6b, 0xa6, 0xe6, 0x39, 0xef, 0x2c, 0xcd, 0x17, 0x23, 0xef,\r
+  0x6c, 0x52, 0xfe, 0x33, 0xad, 0x5a, 0x95, 0xc9, 0xfc, 0x6c, 0x5d, 0x6f,\r
+  0x93, 0x2e, 0x67, 0x86, 0xe6, 0xb9, 0x7c, 0x9f, 0xe6, 0xab, 0x75, 0x5e,\r
+  0xf6, 0xb7, 0x06, 0x9d, 0x57, 0xfa, 0x5c, 0xb5, 0xea, 0x13, 0xf3, 0x67,\r
+  0x55, 0xab, 0x79, 0x6f, 0xd1, 0xe5, 0x84, 0x35, 0xcf, 0xed, 0x39, 0x4f,\r
+  0xf3, 0x5c, 0xe6, 0x4e, 0xcd, 0x77, 0xc3, 0x3e, 0xa2, 0xf9, 0x2d, 0xe0,\r
+  0x77, 0x69, 0x9e, 0xdb, 0x1c, 0xd5, 0xfc, 0x10, 0xe4, 0x31, 0xcd, 0x73,\r
+  0x1b, 0xe2, 0x9a, 0xdf, 0x0b, 0x7e, 0xb7, 0xe6, 0x0f, 0x82, 0x4f, 0x6a,\r
+  0xfe, 0x4a, 0xf0, 0x09, 0xcd, 0x1f, 0x35, 0xf1, 0x37, 0x83, 0x4f, 0x69,\r
+  0xfe, 0x4e, 0xf0, 0xc3, 0x9a, 0x3f, 0x0e, 0xfe, 0x7c, 0xcd, 0x3f, 0x6c,\r
+  0x92, 0x3f, 0x61, 0xe2, 0x9f, 0x05, 0xff, 0x55, 0xcd, 0xbf, 0x64, 0x92,\r
+  0xbf, 0x6a, 0xe2, 0xdf, 0x32, 0xf1, 0xef, 0x9a, 0xf8, 0x16, 0x53, 0xf9,\r
+  0x1f, 0x82, 0xdf, 0xa3, 0xf9, 0x4f, 0xc1, 0x5f, 0xa0, 0x79, 0x27, 0x26,\r
+  0xf9, 0x42, 0xcd, 0x17, 0xd7, 0x8c, 0xe6, 0x9d, 0x6d, 0xe2, 0xab, 0x4d,\r
+  0xfc, 0x7c, 0xf0, 0x23, 0xe9, 0x72, 0x30, 0x56, 0x17, 0x6b, 0xbe, 0xd9,\r
+  0x64, 0x73, 0x73, 0xd5, 0x28, 0xcf, 0x3e, 0xb3, 0x2f, 0x5d, 0x3e, 0xf8,\r
+  0x8b, 0x34, 0xbf, 0xa2, 0x66, 0xb4, 0x6d, 0xdd, 0xe0, 0xf7, 0x6b, 0xfe,\r
+  0x6c, 0x53, 0x39, 0xbc, 0x76, 0xf6, 0x6a, 0x7e, 0xd0, 0x24, 0x8f, 0xd7,\r
+  0x8c, 0xca, 0xf7, 0x9a, 0xca, 0x39, 0x68, 0x6e, 0xbf, 0x69, 0x1c, 0xae,\r
+  0x84, 0xfc, 0x12, 0xcd, 0x5f, 0x07, 0xfe, 0x80, 0xe6, 0x6f, 0x32, 0xd9,\r
+  0xdf, 0x6d, 0xe2, 0x4f, 0xd4, 0xa8, 0xf8, 0xc1, 0xf1, 0x8c, 0x7f, 0x0e,\r
+  0x6a, 0x9e, 0xfd, 0xe7, 0xd2, 0x34, 0x5f, 0x33, 0xca, 0x3f, 0x0b, 0xfe,\r
+  0x32, 0xcd, 0xbf, 0x02, 0xfe, 0x90, 0xe6, 0xd9, 0x97, 0x0e, 0x6b, 0xfe,\r
+  0x55, 0xc8, 0xbf, 0xae, 0xf9, 0xdf, 0x83, 0xbf, 0x42, 0xf3, 0x1f, 0x82,\r
+  0xbf, 0x5c, 0xf3, 0x9f, 0x9a, 0xe4, 0x3c, 0xb6, 0x57, 0x6a, 0xde, 0x8a,\r
+  0xc5, 0x77, 0x95, 0xe6, 0x8b, 0x6b, 0x47, 0xed, 0xe3, 0xa6, 0xbc, 0xdc,\r
+  0xdf, 0x7c, 0x44, 0x9c, 0x7f, 0x22, 0x45, 0xfb, 0x04, 0xc7, 0x3b, 0x41,\r
+  0x83, 0xc4, 0x7b, 0xc0, 0x3c, 0x3a, 0xa6, 0xe9, 0xdf, 0x24, 0x15, 0xf4,\r
+  0x99, 0xa6, 0xfc, 0x8f, 0xa9, 0xd0, 0xd4, 0xd0, 0xd4, 0x22, 0x94, 0x7d,\r
+  0xa1, 0xe0, 0x7d, 0xa3, 0x89, 0x1e, 0x21, 0xa6, 0x1e, 0x7a, 0x4c, 0xd2,\r
+  0x1a, 0x5a, 0x2d, 0xe5, 0xb5, 0x14, 0x14, 0xbc, 0xa7, 0x78, 0xe8, 0x38,\r
+  0x31, 0x2d, 0xa7, 0xfb, 0x25, 0x55, 0xfa, 0x0a, 0xad, 0xaf, 0x04, 0xdd,\r
+  0xa4, 0x29, 0xa7, 0xab, 0xd0, 0xe2, 0x02, 0x49, 0xab, 0xe9, 0x6c, 0xc1,\r
+  0xfb, 0x90, 0xd2, 0x57, 0x6b, 0x7d, 0x35, 0x34, 0x03, 0x82, 0xe3, 0x8f,\r
+  0x41, 0xff, 0x4d, 0x1c, 0x7b, 0x4a, 0xe9, 0x4e, 0x49, 0x2b, 0xe8, 0x3e,\r
+  0x49, 0xd3, 0xf2, 0x6a, 0xca, 0x17, 0x4c, 0x2b, 0xc9, 0x2b, 0x69, 0x2b,\r
+  0x55, 0x49, 0x9a, 0x4b, 0xd5, 0x82, 0xe3, 0xce, 0x7c, 0x0a, 0xc1, 0xce,\r
+  0x86, 0x9d, 0x6b, 0xae, 0xe0, 0xf8, 0x9a, 0x4f, 0x4f, 0x13, 0xd3, 0x52,\r
+  0x7a, 0x13, 0x34, 0x07, 0xed, 0x75, 0x48, 0xba, 0x89, 0x16, 0x40, 0xef,\r
+  0xc2, 0xae, 0xc6, 0xe9, 0x5c, 0x2d, 0xcf, 0xc5, 0x08, 0x2e, 0x14, 0x3c,\r
+  0x9e, 0x2a, 0xed, 0x41, 0xbd, 0x6e, 0xc1, 0xb4, 0x9b, 0xe6, 0x49, 0xba,\r
+  0x9e, 0x96, 0x08, 0xde, 0x33, 0x72, 0xe8, 0x0d, 0x52, 0xf4, 0x3f, 0x24,\r
+  0x6d, 0xa1, 0x66, 0xc1, 0xfb, 0xc4, 0x5a, 0x99, 0xaf, 0x04, 0xbb, 0x1a,\r
+  0xd3, 0xc9, 0xc8, 0xf1, 0x4b, 0x49, 0xdb, 0xa8, 0x0e, 0xfa, 0x29, 0x68,\r
+  0x37, 0xcb, 0xa7, 0xa0, 0xdc, 0x9f, 0x4a, 0x5a, 0x46, 0xcf, 0xea, 0xf4,\r
+  0xaf, 0x34, 0xfd, 0x1d, 0xe8, 0x54, 0xad, 0x67, 0xfa, 0x94, 0xa4, 0x2e,\r
+  0x79, 0x1f, 0xe3, 0xf4, 0xab, 0x92, 0x5a, 0xe8, 0xd7, 0x92, 0xe2, 0x4c,\r
+  0xa1, 0xe9, 0x6b, 0x92, 0x0a, 0x7a, 0x57, 0xd3, 0xff, 0x4d, 0x1c, 0xa3,\r
+  0x0d, 0x7a, 0x59, 0xd2, 0x25, 0xf4, 0x47, 0xe2, 0x58, 0xdb, 0x28, 0xeb,\r
+  0x9f, 0x81, 0x9d, 0xb4, 0x54, 0x30, 0xdd, 0x42, 0x65, 0x92, 0x56, 0xd3,\r
+  0x19, 0x82, 0xe3, 0xef, 0x59, 0xf4, 0x8f, 0xa4, 0x68, 0xbd, 0xe0, 0xb8,\r
+  0xbb, 0x99, 0x72, 0x05, 0xc7, 0xdc, 0x95, 0x32, 0x5f, 0x19, 0x7a, 0x58,\r
+  0x24, 0xd3, 0xe5, 0xe4, 0x17, 0x1c, 0xeb, 0xd5, 0x38, 0xcd, 0xc6, 0x8e,\r
+  0xaf, 0x68, 0x39, 0x9d, 0x90, 0xd4, 0x49, 0xff, 0xac, 0xe9, 0xf3, 0x92,\r
+  0xba, 0xe9, 0x5f, 0x88, 0xf7, 0x9a, 0x20, 0x7d, 0x2a, 0x69, 0x3b, 0xcd,\r
+  0x17, 0x4c, 0x07, 0x68, 0xa5, 0xf4, 0xab, 0xd5, 0x32, 0x7f, 0x39, 0x4e,\r
+  0x17, 0x77, 0x4b, 0xba, 0x8e, 0xee, 0x95, 0xf4, 0x4c, 0xfa, 0xad, 0xa4,\r
+  0xad, 0x74, 0xa6, 0xb4, 0x5b, 0x4e, 0x73, 0x84, 0x4a, 0x97, 0x0b, 0x65,\r
+  0x57, 0x21, 0xe9, 0x32, 0xea, 0xd7, 0x74, 0x8b, 0xa6, 0x5f, 0xd1, 0xf4,\r
+  0x1c, 0xe9, 0x97, 0x6b, 0x64, 0xf9, 0x15, 0xba, 0x7d, 0x15, 0xba, 0x3d,\r
+  0x95, 0x38, 0x95, 0x38, 0x24, 0x2d, 0xa6, 0x47, 0x25, 0x9d, 0x43, 0x3f,\r
+  0xd2, 0xe9, 0x1f, 0x4b, 0xda, 0x4f, 0x35, 0xd2, 0x6f, 0x3b, 0xa4, 0x5d,\r
+  0x15, 0xf2, 0xcf, 0x94, 0xfe, 0xaa, 0xf2, 0x55, 0x43, 0xfe, 0x2d, 0x4d,\r
+  0xbf, 0x2d, 0xe9, 0x14, 0xba, 0x5e, 0xd2, 0x72, 0x5a, 0x25, 0x14, 0x3d,\r
+  0x4b, 0xfa, 0x75, 0x8d, 0xb4, 0x67, 0xff, 0x7e, 0x46, 0x52, 0x07, 0xfd,\r
+  0x4c, 0xa7, 0xff, 0x55, 0xd3, 0x7f, 0xd3, 0xf4, 0xa4, 0xa4, 0xb3, 0xe8,\r
+  0x2d, 0x9d, 0x7e, 0x5b, 0xd2, 0x1e, 0xb2, 0xc9, 0x72, 0x36, 0x93, 0x4b,\r
+  0xd2, 0x4a, 0x6a, 0x94, 0x34, 0x40, 0x2d, 0xd2, 0xff, 0x17, 0xcb, 0xf2,\r
+  0x6b, 0x71, 0x3a, 0xfa, 0xa6, 0xa4, 0x36, 0xba, 0x56, 0xd2, 0xf9, 0x74,\r
+  0x9d, 0xa4, 0x79, 0x74, 0x54, 0xd2, 0x4e, 0xfa, 0x8e, 0xa4, 0x21, 0xba,\r
+  0x41, 0xd2, 0x99, 0x74, 0xa3, 0xa6, 0x37, 0x49, 0x3a, 0x48, 0xdf, 0xd5,\r
+  0xf9, 0xbf, 0x27, 0x69, 0x1d, 0xfd, 0x83, 0xa4, 0xb3, 0xe9, 0x66, 0x49,\r
+  0xe7, 0xd1, 0xf7, 0xb5, 0xfe, 0x16, 0x4d, 0xff, 0x87, 0xa4, 0x76, 0xba,\r
+  0x55, 0xa7, 0x6f, 0x93, 0xb4, 0x9c, 0xee, 0xd1, 0xf4, 0x01, 0x4d, 0x1f,\r
+  0x94, 0xb4, 0x8f, 0x1e, 0x96, 0xb4, 0x86, 0x7e, 0x28, 0xe9, 0x02, 0x7a,\r
+  0x42, 0xd2, 0x19, 0xf4, 0x13, 0x49, 0x27, 0xd2, 0x93, 0x92, 0xe6, 0xd3,\r
+  0x0b, 0x92, 0x4e, 0xa6, 0x17, 0x49, 0xad, 0xef, 0x97, 0x74, 0x1c, 0x78,\r
+  0x59, 0xdb, 0xbf, 0x22, 0xe9, 0x24, 0xfa, 0x85, 0xa4, 0x16, 0xfa, 0x9f,\r
+  0x92, 0x9e, 0x4d, 0xff, 0x4b, 0x52, 0x2f, 0xbd, 0x2e, 0x69, 0x11, 0xfd,\r
+  0x5e, 0xe7, 0x7b, 0x47, 0xd2, 0x42, 0xfa, 0x83, 0xa4, 0x6a, 0x3d, 0xd4,\r
+  0xe2, 0xf7, 0x3d, 0xdd, 0x9e, 0xf7, 0x35, 0xfd, 0x40, 0xd3, 0x3f, 0x49,\r
+  0x3a, 0x97, 0xfe, 0x53, 0x52, 0x3f, 0xfd, 0x59, 0x8f, 0xc7, 0x87, 0x5a,\r
+  0xff, 0x17, 0x9d, 0xff, 0xaf, 0x9a, 0x7e, 0xa4, 0xe9, 0xc7, 0x92, 0xd6,\r
+  0xd3, 0x27, 0x92, 0x9e, 0x4b, 0xff, 0x47, 0xf7, 0xff, 0xbf, 0x24, 0xdd,\r
+  0x4c, 0x39, 0x42, 0xd1, 0x3c, 0x49, 0x17, 0xd1, 0x04, 0x49, 0x17, 0xd2,\r
+  0x44, 0x4d, 0x4b, 0x34, 0x9d, 0xa4, 0xf5, 0x93, 0x75, 0x7a, 0x8a, 0xa6,\r
+  0x53, 0x25, 0x2d, 0xa1, 0x69, 0x92, 0x36, 0xd1, 0x74, 0x49, 0x57, 0xd1,\r
+  0x0c, 0x49, 0xb7, 0x91, 0x4f, 0x52, 0xb5, 0xbe, 0x6b, 0xf5, 0xfa, 0xe6,\r
+  0xf4, 0x2c, 0x49, 0x7b, 0x69, 0xb6, 0x50, 0x71, 0xf4, 0x0c, 0x6d, 0x5f,\r
+  0x29, 0xe9, 0x56, 0xaa, 0x95, 0x74, 0x23, 0x2d, 0xd2, 0xb4, 0x41, 0xd2,\r
+  0x15, 0xd4, 0x24, 0x54, 0x1c, 0x5e, 0x26, 0x69, 0x0f, 0xb5, 0xea, 0xf4,\r
+  0x72, 0x6d, 0xd7, 0xa6, 0xe9, 0x0a, 0x49, 0xab, 0xa8, 0x5d, 0x28, 0x3f,\r
+  0xe8, 0x12, 0xca, 0x2f, 0xd6, 0xe8, 0xf4, 0x5a, 0x4d, 0xd7, 0x69, 0xda,\r
+  0x2d, 0x94, 0x5f, 0xad, 0xd7, 0xe9, 0x0d, 0x42, 0xf9, 0x57, 0x8f, 0x50,\r
+  0x7e, 0x1c, 0x10, 0x6a, 0xbc, 0x37, 0x0a, 0xe5, 0xc7, 0xbd, 0x42, 0x8d,\r
+  0xfb, 0x36, 0xc1, 0xe7, 0xd1, 0xa9, 0xd4, 0x21, 0x69, 0x19, 0x6d, 0x16,\r
+  0x7c, 0x26, 0x3d, 0x83, 0xfe, 0x9d, 0x98, 0x6e, 0x27, 0xa7, 0xdc, 0x07,\r
+  0x0c, 0xb2, 0x4b, 0x3a, 0x9d, 0xb6, 0x0a, 0x3e, 0x77, 0xaa, 0x38, 0xd5,\r
+  0x88, 0x93, 0xe7, 0x73, 0x92, 0xaa, 0x7c, 0x4d, 0xf0, 0x9b, 0x1f, 0x10,\r
+  0x53, 0x2b, 0x3d, 0x24, 0xe9, 0x0e, 0x7a, 0x5c, 0x52, 0x15, 0xf7, 0x59,\r
+  0x5e, 0x2c, 0xe9, 0x2c, 0xea, 0x14, 0x7c, 0x1e, 0xf5, 0x91, 0x43, 0xf0,\r
+  0x1d, 0x48, 0x95, 0xb7, 0x14, 0xf5, 0xdd, 0x45, 0xea, 0x9e, 0xe5, 0x26,\r
+  0x75, 0xbe, 0x3d, 0x8a, 0x7d, 0x3c, 0x0f, 0xf4, 0x55, 0x5c, 0x7c, 0x0a,\r
+  0xf8, 0x12, 0x44, 0xea, 0x0e, 0xe6, 0x26, 0x75, 0xa6, 0xe5, 0x1f, 0xd6,\r
+  0x7f, 0x08, 0x7d, 0x97, 0xd6, 0x57, 0x6a, 0xfd, 0x2c, 0x93, 0xde, 0x8a,\r
+  0x4b, 0xd3, 0x76, 0xad, 0xaf, 0xd2, 0x72, 0x2e, 0xff, 0x66, 0x5d, 0xfe,\r
+  0x34, 0xe8, 0x2f, 0xd5, 0xfa, 0x6a, 0x53, 0xfd, 0xe9, 0xfc, 0xd5, 0xd0,\r
+  0x1f, 0xd5, 0x7a, 0x3e, 0xd7, 0x8b, 0x53, 0xf4, 0xcd, 0xd0, 0x3f, 0xa1,\r
+  0xf5, 0x7c, 0xd6, 0xe7, 0x7b, 0x06, 0x9f, 0xc5, 0xef, 0xd4, 0xe5, 0x07,\r
+  0xa0, 0xff, 0x58, 0xeb, 0xed, 0x7c, 0x3e, 0x00, 0x2d, 0xae, 0x50, 0x77,\r
+  0xc5, 0xdd, 0xee, 0xb9, 0x98, 0x31, 0x17, 0xa8, 0x9f, 0xa9, 0x58, 0xcc,\r
+  0x27, 0x06, 0x61, 0xa1, 0xf2, 0xd9, 0x51, 0xf7, 0x53, 0x90, 0xe4, 0xd9,\r
+  0xca, 0x8c, 0xa5, 0x14, 0x77, 0xbf, 0x80, 0x71, 0x2c, 0xb3, 0x94, 0x90,\r
+  0xd7, 0x1a, 0xf5, 0x3f, 0x83, 0x98, 0xcf, 0x39, 0x7e, 0x22, 0xeb, 0x97,\r
+  0x69, 0xe1, 0xb2, 0x71, 0x9a, 0xed, 0xe3, 0x7e, 0x37, 0x59, 0x6c, 0x51,\r
+  0xdf, 0xbf, 0xa0, 0x7c, 0x8f, 0xe1, 0xb5, 0x79, 0x6c, 0x56, 0x8c, 0x3d,\r
+  0xdf, 0x95, 0x66, 0x54, 0xf0, 0x7e, 0x8c, 0xb3, 0x8f, 0x9b, 0x23, 0x43,\r
+  0xbf, 0x28, 0xa0, 0x7e, 0x23, 0x8f, 0xfa, 0x2d, 0xf9, 0xb4, 0xdb, 0xb7,\r
+  0x14, 0xd6, 0x7c, 0xc7, 0x33, 0x32, 0xb7, 0x2d, 0xd5, 0x4f, 0x96, 0xd9,\r
+  0xf0, 0xcb, 0x7c, 0x65, 0x85, 0x7a, 0x87, 0x99, 0x70, 0x3f, 0x8e, 0x74,\r
+  0x9e, 0xe8, 0x17, 0xb9, 0x19, 0x3d, 0xe7, 0x9a, 0x57, 0xa1, 0xee, 0x5e,\r
+  0x01, 0x91, 0x47, 0x01, 0x83, 0x4b, 0x6d, 0xc1, 0xbe, 0x57, 0x80, 0x3c,\r
+  0x0e, 0xa9, 0x6f, 0x3e, 0x8d, 0x3e, 0x9d, 0x7f, 0xd5, 0x69, 0xf4, 0x39,\r
+  0xd0, 0xf3, 0x98, 0x75, 0x57, 0xa8, 0x7b, 0x47, 0xa0, 0x25, 0x8f, 0xe6,\r
+  0x75, 0x87, 0x41, 0x73, 0x31, 0x0f, 0x18, 0xab, 0x81, 0xe3, 0x43, 0x09,\r
+  0xff, 0x63, 0x14, 0x72, 0xe6, 0xd9, 0xb8, 0x6d, 0x3c, 0x0a, 0x53, 0x9c,\r
+  0x06, 0x45, 0x7d, 0x3f, 0xc3, 0x39, 0xd3, 0xe5, 0xf4, 0x52, 0xa3, 0x33,\r
+  0x9f, 0xa6, 0x38, 0x2d, 0x19, 0x49, 0x03, 0xf8, 0x72, 0x8b, 0xd7, 0x59,\r
+  0x6e, 0x29, 0x72, 0x2e, 0x47, 0x3c, 0x10, 0x52, 0x33, 0x01, 0xe3, 0xdf,\r
+  0x20, 0xac, 0x54, 0xe4, 0x5c, 0x42, 0x81, 0xd6, 0x7c, 0x0a, 0x2c, 0xcf,\r
+  0x95, 0xa3, 0x6b, 0xd8, 0x5d, 0x46, 0xa0, 0x2d, 0x97, 0x8e, 0x8f, 0x70,\r
+  0xca, 0x62, 0x77, 0xd9, 0xa3, 0xfe, 0x2d, 0x54, 0x6a, 0x0f, 0xac, 0xcc,\r
+  0xa7, 0x06, 0x27, 0x66, 0xc0, 0xfd, 0x2c, 0xcf, 0x9d, 0xe3, 0xa4, 0xc3,\r
+  0xf1, 0x59, 0xd4, 0xff, 0xcf, 0x64, 0x73, 0xe4, 0x61, 0xfc, 0xfb, 0x10,\r
+  0x21, 0x58, 0x1b, 0x68, 0x2f, 0xa0, 0x32, 0xfb, 0x14, 0x8a, 0xfb, 0x8b,\r
+  0xc8, 0xee, 0x8c, 0xfa, 0x6f, 0xa6, 0x4b, 0xed, 0x81, 0x76, 0xc8, 0x57,\r
+  0xaa, 0x1e, 0x86, 0xc8, 0x6b, 0xeb, 0x6f, 0xcf, 0x95, 0xe3, 0x60, 0xc8,\r
+  0x7e, 0xee, 0xa8, 0x50, 0xfe, 0x13, 0x75, 0x6f, 0xc4, 0xcc, 0xb9, 0x40,\r
+  0x7b, 0x99, 0x5a, 0x17, 0xa3, 0x85, 0x4d, 0x56, 0xb4, 0xdc, 0xc3, 0xbe,\r
+  0x61, 0xc1, 0x0c, 0x78, 0x8d, 0xa8, 0xff, 0x39, 0x8c, 0x11, 0x6c, 0x98,\r
+  0x5a, 0x5d, 0xd6, 0xdd, 0xfe, 0x02, 0xb2, 0x58, 0x0b, 0xe4, 0x3c, 0xf2,\r
+  0x98, 0x26, 0xf5, 0x98, 0xee, 0x76, 0x37, 0x2a, 0x6f, 0xf1, 0x7d, 0x05,\r
+  0x73, 0x37, 0xaa, 0x3f, 0x5f, 0xcf, 0xe9, 0x6e, 0x5f, 0x2b, 0xfc, 0x7e,\r
+  0xb7, 0x6f, 0x19, 0x9e, 0x6a, 0x4e, 0x55, 0x5b, 0x0e, 0xe8, 0xb6, 0xec,\r
+  0x76, 0xe7, 0x23, 0xcd, 0x5e, 0x97, 0xc7, 0x54, 0xc8, 0xb6, 0x08, 0x53,\r
+  0x5b, 0x2c, 0xdc, 0x96, 0x67, 0xb0, 0xee, 0x5c, 0x72, 0xcc, 0x66, 0x09,\r
+  0x97, 0x85, 0x47, 0xc9, 0x6a, 0x29, 0x90, 0x3e, 0x6f, 0x43, 0x19, 0xdf,\r
+  0xa8, 0x50, 0x77, 0xd2, 0x40, 0x77, 0x21, 0x4e, 0x95, 0x16, 0xac, 0x93,\r
+  0x40, 0xb7, 0x07, 0x33, 0x98, 0x43, 0x31, 0x77, 0x3d, 0xcf, 0x1a, 0xf5,\r
+  0x43, 0xe3, 0x41, 0x7f, 0xf9, 0x6d, 0x85, 0x8b, 0x02, 0xeb, 0x3d, 0xc4,\r
+  0xa5, 0x9e, 0x8d, 0x1e, 0xe6, 0x21, 0xfa, 0x4e, 0xa0, 0xb8, 0xaf, 0x10,\r
+  0x65, 0xf5, 0xaf, 0x2f, 0x94, 0xe7, 0xa6, 0x40, 0x8f, 0x97, 0x02, 0x01,\r
+  0x0f, 0xc5, 0x5b, 0x16, 0x92, 0xbf, 0xb5, 0xbf, 0xdb, 0x8d, 0x1c, 0x85,\r
+  0xf0, 0xce, 0x1c, 0xd8, 0xb8, 0x2c, 0x45, 0x56, 0x2f, 0x25, 0x02, 0xb9,\r
+  0x24, 0xea, 0x03, 0xb2, 0x54, 0xc4, 0x01, 0xfc, 0x72, 0x9f, 0x6e, 0xd4,\r
+  0x63, 0x12, 0xf7, 0xd7, 0x92, 0xdb, 0xe8, 0x17, 0x5e, 0xac, 0x01, 0x0f,\r
+  0x7a, 0x6d, 0xe1, 0x33, 0x3c, 0xe4, 0xb7, 0x55, 0xa8, 0x77, 0x16, 0x01,\r
+  0x1f, 0xb7, 0x33, 0x87, 0x02, 0xa5, 0x6e, 0xc4, 0x70, 0x1b, 0x25, 0x7c,\r
+  0x2e, 0x8c, 0x0e, 0xac, 0x21, 0xef, 0xf7, 0x79, 0xd0, 0xea, 0x3a, 0xd8,\r
+  0x17, 0xa0, 0x2c, 0x43, 0xf6, 0xef, 0xde, 0x0a, 0x75, 0x5f, 0x0f, 0x6c,\r
+  0x2d, 0xc2, 0x38, 0xf1, 0xdb, 0x94, 0x5c, 0xb4, 0x7f, 0x22, 0xaa, 0x9c,\r
+  0x0b, 0x07, 0x6e, 0xb4, 0xa1, 0xc7, 0xc6, 0x56, 0xd8, 0x16, 0x89, 0x19,\r
+  0x34, 0xdf, 0xed, 0x42, 0x1f, 0xca, 0x28, 0x30, 0x50, 0x8c, 0x76, 0x54,\r
+  0x92, 0xdf, 0x51, 0xee, 0x08, 0x6c, 0x2d, 0xc6, 0x0c, 0x54, 0xe1, 0xae,\r
+  0x0c, 0xef, 0x18, 0x50, 0x65, 0x58, 0x28, 0xd7, 0xba, 0xbb, 0x7b, 0x90,\r
+  0xda, 0x86, 0x5d, 0x8e, 0x46, 0x87, 0x8b, 0xb6, 0x3a, 0x0c, 0x5a, 0x50,\r
+  0x62, 0xc3, 0x18, 0x71, 0xa4, 0xf2, 0x18, 0xdc, 0x2f, 0xa7, 0x9e, 0xab,\r
+  0x47, 0x75, 0x4c, 0xf9, 0xbc, 0xfa, 0xbd, 0xee, 0x79, 0x0e, 0x78, 0xf6,\r
+  0x0e, 0x65, 0xe1, 0x80, 0xc5, 0x6e, 0x7f, 0x08, 0x91, 0x38, 0xcf, 0x51,\r
+  0x9e, 0x9b, 0x2d, 0xdd, 0x2e, 0xa5, 0x0d, 0x0e, 0xac, 0x01, 0xf7, 0x13,\r
+  0x90, 0xb9, 0x1c, 0x51, 0xdf, 0x4a, 0xdc, 0x5f, 0xf3, 0x1c, 0x1e, 0x87,\r
+  0xc7, 0x70, 0x61, 0x2c, 0xf9, 0x9d, 0xcb, 0xd3, 0x15, 0xea, 0x1d, 0x84,\r
+  0xb9, 0xce, 0x89, 0x18, 0xc4, 0xb9, 0x08, 0x39, 0x8d, 0x56, 0x2b, 0x79,\r
+  0x1d, 0x85, 0x0e, 0x93, 0x4e, 0x88, 0xa4, 0x38, 0xe8, 0xf8, 0xd6, 0x1e,\r
+  0xfb, 0x0e, 0x9e, 0x61, 0xe8, 0x2c, 0x72, 0xd4, 0x89, 0x7e, 0x5e, 0xa1,\r
+  0xde, 0xe1, 0x94, 0x09, 0x15, 0xed, 0x04, 0x79, 0x44, 0x5a, 0xf7, 0x0b,\r
+  0x3d, 0x5f, 0xfd, 0xa2, 0x08, 0x3a, 0x8e, 0xc0, 0xfd, 0x46, 0xb1, 0xf6,\r
+  0x61, 0xd6, 0xff, 0xba, 0x82, 0xef, 0x21, 0xac, 0x9f, 0xa8, 0x63, 0x9b,\r
+  0x57, 0x6c, 0x81, 0xb7, 0x14, 0x98, 0xe2, 0xed, 0x5b, 0x15, 0xea, 0x7d,\r
+  0x58, 0x19, 0x22, 0x60, 0xdc, 0x2d, 0xa3, 0xcc, 0xfa, 0x89, 0x14, 0xf0,\r
+  0x94, 0xa0, 0x77, 0xfb, 0x65, 0x34, 0x6b, 0x44, 0xee, 0x8c, 0xcc, 0x77,\r
+  0x10, 0xb2, 0x51, 0x8b, 0x0b, 0xd8, 0xa3, 0xc4, 0x06, 0x83, 0xdf, 0xb1,\r
+  0x09, 0x2a, 0xcf, 0x8b, 0xfa, 0xca, 0x40, 0xa3, 0xee, 0xd2, 0x2c, 0xf9,\r
+  0x7d, 0xc6, 0x7d, 0xa5, 0x45, 0xf0, 0x9c, 0x05, 0x62, 0x0a, 0x6d, 0xdc,\r
+  0x30, 0x81, 0x1a, 0x8c, 0x89, 0x18, 0xff, 0x2d, 0xe0, 0x02, 0x1b, 0x50,\r
+  0x52, 0x59, 0x09, 0x3c, 0x76, 0x22, 0x46, 0x62, 0x9d, 0x5c, 0x2f, 0x7a,\r
+  0x76, 0x2d, 0xbb, 0xfd, 0x03, 0x54, 0x6f, 0x65, 0xfb, 0x46, 0xc3, 0x81,\r
+  0x33, 0x83, 0x8d, 0xbc, 0xee, 0x2d, 0xdd, 0x13, 0xe4, 0x0d, 0x54, 0xc8,\r
+  0x38, 0xfc, 0x17, 0xb4, 0x9d, 0xfb, 0x10, 0xc0, 0x19, 0x8d, 0xe7, 0x9b,\r
+  0xc7, 0x85, 0xfd, 0xf4, 0xbf, 0x2a, 0xd4, 0xbb, 0xb8, 0x7e, 0x51, 0xa2,\r
+  0xfb, 0x5d, 0x26, 0xe0, 0x3d, 0xbe, 0x4e, 0x5e, 0x23, 0x62, 0x32, 0x46,\r
+  0x69, 0x92, 0x1c, 0x03, 0xa1, 0x4b, 0xe2, 0x72, 0xac, 0x32, 0xfe, 0x77,\r
+  0x13, 0xe9, 0xf2, 0xb3, 0xe5, 0xeb, 0xa5, 0x3c, 0xbd, 0x0e, 0x9c, 0x95,\r
+  0x7a, 0xff, 0xf2, 0x4d, 0x42, 0x5f, 0x2f, 0x91, 0xf1, 0x23, 0x50, 0x3a,\r
+  0x19, 0xa3, 0x33, 0x47, 0x46, 0x89, 0xb4, 0x5d, 0xfe, 0x69, 0xed, 0xca,\r
+  0xb3, 0xec, 0xbc, 0x95, 0x2a, 0xd6, 0xf4, 0xf8, 0xa6, 0xc0, 0xcf, 0xcf,\r
+  0x85, 0xce, 0x25, 0xdb, 0x9f, 0xd6, 0x97, 0x64, 0xe9, 0x23, 0x19, 0xbd,\r
+  0x55, 0xfb, 0xf7, 0x34, 0xb3, 0xde, 0x1f, 0x25, 0xb7, 0xc5, 0x65, 0x29,\r
+  0xb4, 0x8c, 0xe6, 0x2f, 0xcb, 0xca, 0xbf, 0x75, 0x4c, 0xf9, 0x73, 0xb2,\r
+  0xf4, 0x43, 0x63, 0xf4, 0xd5, 0x59, 0xfa, 0xd8, 0x18, 0xfd, 0xdc, 0x2c,\r
+  0xfd, 0xae, 0x8c, 0x9e, 0x77, 0x27, 0x1e, 0xbf, 0x85, 0x66, 0x7d, 0xcb,\r
+  0x79, 0xe4, 0x6e, 0xcb, 0xb3, 0x78, 0x2c, 0x6a, 0xbe, 0x78, 0x9c, 0x97,\r
+  0x54, 0x2a, 0x1f, 0x57, 0x73, 0xd5, 0x07, 0x2f, 0x29, 0xc8, 0xf4, 0xad,\r
+  0x4d, 0xeb, 0x54, 0xdf, 0x76, 0xa2, 0x6f, 0x05, 0x99, 0x72, 0x3b, 0xcc,\r
+  0xba, 0x96, 0x30, 0xca, 0x1d, 0xcd, 0xd7, 0x9d, 0x95, 0x2f, 0x28, 0xf3,\r
+  0x19, 0xda, 0x6f, 0x7a, 0x2b, 0xb5, 0xdf, 0xb8, 0x67, 0x4a, 0xbf, 0xe1,\r
+  0x5d, 0x98, 0xcb, 0xeb, 0xaf, 0x54, 0xef, 0x03, 0x7b, 0xba, 0xa7, 0x23,\r
+  0xf6, 0xec, 0xc3, 0x7d, 0x28, 0x4f, 0x9e, 0x89, 0xfb, 0x83, 0x16, 0x00,\r
+  0x6b, 0xd6, 0xd8, 0xbc, 0xcd, 0x4e, 0xde, 0x3f, 0x37, 0x20, 0x07, 0xef,\r
+  0x41, 0x58, 0xa9, 0xd6, 0x72, 0xc3, 0xfb, 0xe1, 0xe6, 0x41, 0x27, 0xe2,\r
+  0xa1, 0x5d, 0xee, 0x47, 0x90, 0x59, 0x36, 0x0f, 0x38, 0x60, 0xef, 0xe2,\r
+  0x73, 0x77, 0xf7, 0xe6, 0x20, 0xbf, 0x29, 0xe0, 0xbd, 0x8a, 0xdf, 0x38,\r
+  0xbb, 0xc4, 0x6e, 0xf7, 0xc5, 0xbc, 0x36, 0x50, 0x52, 0x0e, 0x76, 0xbf,\r
+  0x0a, 0xf2, 0x7a, 0xe2, 0x2d, 0xcb, 0x71, 0xf2, 0xec, 0xef, 0x9d, 0x46,\r
+  0x1e, 0xfb, 0xe8, 0x98, 0xee, 0xac, 0x54, 0x67, 0x92, 0xa8, 0x7b, 0x2f,\r
+  0xd2, 0xdc, 0x0e, 0xab, 0x88, 0xfa, 0x70, 0x66, 0x04, 0x3f, 0x13, 0x77,\r
+  0x48, 0x8f, 0x3e, 0x93, 0xb0, 0x6d, 0xbc, 0x92, 0x64, 0x9c, 0xdd, 0xed,\r
+  0x7b, 0xd8, 0x34, 0xf6, 0x36, 0x29, 0x1b, 0xd6, 0xba, 0x78, 0xe0, 0x76,\r
+  0x72, 0xd7, 0x2b, 0x9d, 0x5d, 0xfe, 0x12, 0x5d, 0xa4, 0x75, 0x23, 0xf6,\r
+  0x6b, 0xe4, 0xbe, 0x52, 0xa8, 0xd7, 0x50, 0xfa, 0x47, 0xfa, 0xa6, 0xa7,\r
+  0x50, 0xa4, 0xc7, 0xed, 0x32, 0x3d, 0x6e, 0x1b, 0xdd, 0x3e, 0x69, 0x6b,\r
+  0xe8, 0x75, 0x72, 0x45, 0x25, 0xe7, 0xe6, 0xb6, 0x1e, 0xe0, 0xbe, 0x61,\r
+  0xe7, 0xc2, 0x58, 0xb9, 0x31, 0x32, 0xb0, 0xca, 0x85, 0x15, 0x47, 0x95,\r
+  0x23, 0x95, 0xea, 0xbd, 0x6a, 0xe0, 0xc8, 0x54, 0xd8, 0x55, 0xc8, 0xfa,\r
+  0x1a, 0x70, 0x97, 0xed, 0xf9, 0xe6, 0x74, 0xa4, 0x27, 0x23, 0xe5, 0xb2,\r
+  0x46, 0xdd, 0xd3, 0x99, 0xda, 0xa2, 0xee, 0x19, 0x4c, 0xed, 0x51, 0xf7,\r
+  0x14, 0xd0, 0x5c, 0x87, 0xe3, 0x9a, 0x11, 0xe7, 0xa5, 0x28, 0xd9, 0x3b,\r
+  0xa5, 0xd0, 0xe5, 0x75, 0x15, 0xba, 0x72, 0xd1, 0x0a, 0x6e, 0xff, 0xf5,\r
+  0x95, 0x2a, 0xae, 0xf7, 0xec, 0x9f, 0x9e, 0x1d, 0x5b, 0x73, 0x0a, 0x73,\r
+  0xa2, 0xee, 0x04, 0xea, 0xf5, 0xb6, 0x78, 0x3d, 0xf5, 0x39, 0x33, 0x71,\r
+  0x47, 0x9b, 0x44, 0xf5, 0x39, 0x13, 0x41, 0x27, 0x83, 0x7a, 0xa9, 0xe7,\r
+  0x6b, 0x5c, 0x6b, 0x89, 0xae, 0x65, 0x22, 0x53, 0x87, 0xe3, 0x80, 0xf8,\r
+  0xd6, 0x88, 0xfd, 0x72, 0xb4, 0xb7, 0x50, 0xc4, 0xfc, 0xb3, 0xe9, 0xa8,\r
+  0xcb, 0x25, 0xcb, 0x89, 0xa3, 0x9c, 0x42, 0x91, 0xaf, 0xe3, 0xfa, 0xb1,\r
+  0x4a, 0xf5, 0x6e, 0xb8, 0xe7, 0xc8, 0xf4, 0x53, 0xf6, 0x90, 0x42, 0xa3,\r
+  0xd1, 0xe5, 0x27, 0xb5, 0x8f, 0x4d, 0xa7, 0x05, 0x6e, 0x9e, 0xf3, 0x62,\r
+  0xcc, 0x96, 0x8b, 0xbc, 0xb3, 0xea, 0xfd, 0x38, 0x11, 0x94, 0x6e, 0xcd,\r
+  0xc5, 0x1e, 0x35, 0x95, 0x6b, 0x9e, 0x00, 0x79, 0x5e, 0x6e, 0x43, 0x6e,\r
+  0x49, 0x86, 0x8f, 0xfa, 0x9e, 0xc6, 0x19, 0xdc, 0xe5, 0xe8, 0xb9, 0x8e,\r
+  0xf5, 0x13, 0x39, 0x9f, 0xd3, 0x71, 0xad, 0xb8, 0x9d, 0x5b, 0x64, 0x91,\r
+  0x3d, 0x2f, 0x34, 0x62, 0x2d, 0x67, 0xd0, 0xb1, 0xe7, 0x5d, 0x18, 0x01,\r
+  0x8e, 0xfb, 0x16, 0x39, 0x77, 0x8f, 0x56, 0xaa, 0xcf, 0x14, 0xd8, 0x67,\r
+  0xb3, 0xc6, 0xc0, 0x5e, 0x68, 0xe7, 0x1e, 0xf2, 0xfe, 0x14, 0xdf, 0x74,\r
+  0x05, 0xd9, 0x82, 0xde, 0x89, 0x85, 0x76, 0xb6, 0x55, 0xf3, 0xf1, 0x24,\r
+  0xf2, 0xf1, 0xbd, 0xce, 0xe9, 0xf4, 0x90, 0x93, 0x47, 0x04, 0x63, 0xe8,\r
+  0x75, 0x8d, 0x96, 0x80, 0xfe, 0xb8, 0x52, 0x62, 0x12, 0x76, 0x75, 0x17,\r
+  0xa5, 0xb0, 0x22, 0xbd, 0x94, 0x9b, 0xfb, 0x0b, 0xf1, 0x19, 0x79, 0xa7,\r
+  0x37, 0x88, 0xf7, 0xa9, 0xfe, 0xe5, 0x93, 0xe4, 0xad, 0xad, 0x7f, 0xe3,\r
+  0x1a, 0xf2, 0xd6, 0xd7, 0x97, 0xfe, 0x2b, 0x79, 0x37, 0x14, 0x5b, 0xf8,\r
+  0xf5, 0x5f, 0x7d, 0xe9, 0x2a, 0xf2, 0x6e, 0xab, 0x2f, 0xe5, 0xdc, 0x0f,\r
+  0xfa, 0xdf, 0x40, 0xf1, 0x8d, 0xb8, 0x47, 0xf6, 0x5c, 0x82, 0x3e, 0xf9,\r
+  0xa6, 0xd1, 0x31, 0xac, 0x8d, 0x14, 0xc6, 0x06, 0x65, 0x5a, 0x53, 0xd8,\r
+  0xeb, 0x41, 0x6d, 0x4e, 0x78, 0xb2, 0xf5, 0x07, 0x23, 0x4e, 0xfe, 0x4c,\r
+  0xa5, 0x7c, 0xce, 0xac, 0x37, 0xda, 0x60, 0xf9, 0x55, 0xcc, 0x56, 0xcf,\r
+  0x01, 0x95, 0x27, 0x87, 0xfd, 0xc2, 0x37, 0x93, 0xa9, 0x6d, 0x85, 0x5d,\r
+  0xb8, 0x0e, 0x6c, 0x7f, 0x26, 0x14, 0xf5, 0xf9, 0x38, 0x8d, 0xfb, 0xa0,\r
+  0xc8, 0x3f, 0xe0, 0xb9, 0x1d, 0x5b, 0x99, 0x2c, 0xa5, 0x54, 0xb4, 0x89,\r
+  0x80, 0x08, 0xa5, 0x4b, 0x2b, 0xcc, 0xff, 0xfb, 0x5a, 0x70, 0xd5, 0xff,\r
+  0xd7, 0x16, 0x5c, 0x25, 0x5b, 0xf0, 0x65, 0xea, 0xe5, 0x4f, 0x94, 0x52,\r
+  0x62, 0x2a, 0xcb, 0x0a, 0x17, 0xbd, 0x56, 0x45, 0xb3, 0xde, 0x53, 0x2d,\r
+  0xf8, 0x3d, 0x79, 0x27, 0x2e, 0xf8, 0xeb, 0xac, 0x4c, 0xdb, 0xc3, 0x28,\r
+  0x83, 0xdb, 0x11, 0xe6, 0x7a, 0xad, 0x05, 0xae, 0x03, 0x2b, 0x9e, 0xb1,\r
+  0x72, 0x3b, 0x64, 0xda, 0x56, 0x90, 0x7f, 0x60, 0xe3, 0x33, 0xb2, 0x4c,\r
+  0xc3, 0x6d, 0xcf, 0x94, 0x7b, 0xd2, 0xee, 0x16, 0xe5, 0xbf, 0xf9, 0x72,\r
+  0xed, 0xb8, 0xfa, 0x4b, 0xb7, 0x58, 0xf5, 0x8d, 0xe3, 0x88, 0x8a, 0x16,\r
+  0x1f, 0x54, 0xaa, 0xcf, 0xb8, 0xe2, 0xfe, 0xf3, 0xa9, 0xcd, 0x96, 0x6b,\r
+  0xe5, 0xcf, 0xa9, 0xe6, 0x1a, 0x56, 0xec, 0xf3, 0x4e, 0xac, 0xf9, 0x1a,\r
+  0xc8, 0x37, 0x50, 0x8b, 0x8d, 0xe3, 0x81, 0x67, 0x9c, 0x98, 0x75, 0x7f,\r
+  0x26, 0x66, 0x8d, 0xd5, 0x3d, 0xf0, 0x39, 0xba, 0xe3, 0x9f, 0xa3, 0xfb,\r
+  0x81, 0x69, 0x8f, 0x52, 0x6d, 0xfc, 0x28, 0xad, 0xf3, 0xdf, 0x87, 0xb3,\r
+  0xed, 0xe9, 0xf2, 0x9d, 0xc8, 0xe4, 0x4b, 0x9f, 0x31, 0xf8, 0x87, 0xef,\r
+  0xae, 0x55, 0xf2, 0x34, 0xc7, 0x11, 0xad, 0x98, 0x2e, 0xe1, 0x88, 0x40,\r
+  0x5e, 0x3f, 0xf3, 0xa5, 0x92, 0x2f, 0x46, 0xcf, 0x98, 0x62, 0x75, 0xe1,\r
+  0x0c, 0xec, 0xf5, 0xb1, 0x44, 0xa8, 0x92, 0x84, 0x43, 0x96, 0xc1, 0x9f,\r
+  0xd1, 0xf1, 0xb8, 0xf0, 0x5a, 0xe5, 0xf2, 0x73, 0x49, 0x9d, 0xcd, 0x6c,\r
+  0xe3, 0xb4, 0x31, 0xee, 0xbf, 0x10, 0x6d, 0xcc, 0xcb, 0x9c, 0x69, 0xb2,\r
+  0x75, 0x23, 0x19, 0x9d, 0x55, 0xfe, 0x12, 0xfd, 0x2d, 0xdd, 0xfe, 0x96,\r
+  0x07, 0x11, 0xe3, 0xd3, 0xf9, 0x54, 0xfb, 0xe3, 0x3a, 0x66, 0xf7, 0xf8,\r
+  0xa6, 0xcb, 0xfb, 0xbb, 0xba, 0x33, 0x62, 0xbf, 0xc3, 0x1d, 0x9c, 0x77,\r
+  0xdb, 0xb8, 0x6f, 0x16, 0xce, 0x4f, 0x65, 0x68, 0x4f, 0xdc, 0xcd, 0xf1,\r
+  0xad, 0xbf, 0xa5, 0x14, 0xa7, 0xa5, 0x6a, 0xd4, 0xd3, 0x45, 0xad, 0xd6,\r
+  0xfe, 0xd6, 0x19, 0x48, 0x55, 0x22, 0xd5, 0x2e, 0x53, 0x33, 0xe5, 0x7e,\r
+  0x64, 0xc5, 0xa9, 0x70, 0x8a, 0x71, 0x07, 0xf1, 0x7e, 0x84, 0x1b, 0x88,\r
+  0x98, 0x29, 0x4a, 0xa9, 0xbf, 0x75, 0x2a, 0x4d, 0xc3, 0x19, 0x2d, 0xea,\r
+  0xfb, 0x31, 0xad, 0x97, 0xf7, 0x45, 0x27, 0xcd, 0xb4, 0x71, 0x9a, 0x3f,\r
+  0xb3, 0x2d, 0x77, 0x45, 0xdd, 0x42, 0xde, 0x3f, 0x47, 0x65, 0x7d, 0xab,\r
+  0xe0, 0x5d, 0xb8, 0x0f, 0xde, 0x8b, 0xfa, 0xb7, 0xac, 0xf4, 0xc1, 0xdb,\r
+  0xa3, 0xbe, 0x3b, 0x68, 0x10, 0xda, 0x3b, 0xe5, 0xf3, 0x18, 0xad, 0xa0,\r
+  0x32, 0x47, 0x0e, 0xda, 0x65, 0x41, 0x14, 0x2b, 0x72, 0x16, 0xd3, 0xac,\r
+  0xc3, 0xcb, 0xe9, 0x4c, 0x27, 0x7f, 0x3a, 0x1c, 0xf5, 0x59, 0xe9, 0x10,\r
+  0x95, 0x39, 0x5d, 0x68, 0xbf, 0x8d, 0xf6, 0x22, 0xed, 0xa0, 0xfd, 0xe4,\r
+  0x9d, 0xe3, 0x75, 0x46, 0xdd, 0x3f, 0xe5, 0xf6, 0x61, 0xbf, 0x5c, 0x2c,\r
+  0x66, 0x25, 0x56, 0xd0, 0x36, 0x4b, 0x19, 0xad, 0xb1, 0x18, 0xb6, 0x69,\r
+  0x96, 0x5c, 0xa6, 0xb8, 0xa1, 0xfe, 0x48, 0x8e, 0x5f, 0xb9, 0xe1, 0xd8,\r
+  0xdf, 0x80, 0x99, 0x98, 0xb5, 0xa7, 0x9d, 0xf4, 0x1b, 0x02, 0xb1, 0x46,\r
+  0x38, 0x6c, 0x6b, 0x9c, 0x0e, 0xd8, 0x3c, 0x4f, 0x2d, 0x8e, 0xdd, 0x72,\r
+  0x1c, 0xf9, 0xc6, 0xea, 0x45, 0x6b, 0xe5, 0xe7, 0xbc, 0x16, 0xab, 0xbc,\r
+  0xff, 0x8c, 0xfe, 0xec, 0x5f, 0x46, 0x7f, 0x57, 0xfa, 0xd4, 0x1f, 0xa5,\r
+  0xe7, 0xcf, 0x18, 0xd9, 0x5f, 0xf6, 0x13, 0xef, 0xf9, 0x76, 0x32, 0x8c,\r
+  0xc5, 0x17, 0x35, 0x5c, 0x64, 0x59, 0x78, 0x95, 0x58, 0x70, 0x95, 0x68,\r
+  0xbe, 0x4a, 0x98, 0x7d, 0xc0, 0x2a, 0x7d, 0xf8, 0x51, 0xf4, 0xa1, 0x80,\r
+  0x4e, 0x95, 0xc7, 0xfd, 0x57, 0x4a, 0xb9, 0xd9, 0x2f, 0xa4, 0x7d, 0xcb,\r
+  0x23, 0xf0, 0x8b, 0xb1, 0xf6, 0xbb, 0xfd, 0x0f, 0x49, 0xfb, 0xf4, 0x5d,\r
+  0x60, 0x6e, 0x95, 0x3a, 0x73, 0x64, 0xef, 0x25, 0x16, 0xf4, 0x3d, 0xee,\r
+  0x3f, 0x8c, 0xd3, 0x50, 0x81, 0xc9, 0xaf, 0x16, 0x55, 0x29, 0x9f, 0x63,\r
+  0x9f, 0xee, 0x83, 0x6f, 0xa5, 0x75, 0xf2, 0x7d, 0x46, 0x95, 0x8a, 0x07,\r
+  0x51, 0xf7, 0x45, 0xf2, 0xec, 0xc2, 0xef, 0x22, 0x0a, 0x70, 0xf2, 0x9d,\r
+  0x26, 0x6f, 0x8b, 0x51, 0x77, 0x1b, 0xdf, 0x11, 0x7c, 0xf3, 0xc9, 0x27,\r
+  0xef, 0x88, 0x6a, 0x1f, 0x5b, 0xa1, 0x3f, 0x0f, 0x1f, 0xa7, 0xee, 0x4d,\r
+  0x5f, 0xc7, 0xee, 0xa5, 0x67, 0xc3, 0xce, 0xb3, 0xd1, 0x2b, 0xcf, 0x87,\r
+  0xaa, 0xcd, 0x5d, 0xfa, 0xb3, 0x73, 0xae, 0xcb, 0x92, 0xa9, 0x2b, 0xea,\r
+  0xfe, 0x5a, 0xe6, 0x3d, 0xc0, 0x3c, 0xf4, 0x31, 0xe0, 0x9f, 0x81, 0x59,\r
+  0xe6, 0xbf, 0x0b, 0x28, 0xa0, 0xec, 0x33, 0x4e, 0xfa, 0x5d, 0xce, 0x78,\r
+  0xef, 0x77, 0xec, 0xfa, 0x2c, 0xd9, 0x93, 0x1e, 0x97, 0x16, 0xdd, 0x36,\r
+  0x1b, 0xda, 0x66, 0x53, 0xe3, 0x72, 0x19, 0x59, 0x85, 0xd9, 0xb6, 0xef,\r
+  0x73, 0x6c, 0x0f, 0x69, 0xdb, 0x2f, 0x5b, 0xff, 0x78, 0x32, 0x87, 0xbe,\r
+  0x53, 0x07, 0xab, 0x54, 0x1c, 0x19, 0x3b, 0x5e, 0x81, 0x0d, 0xa5, 0x14,\r
+  0xdf, 0x70, 0x04, 0x63, 0xc6, 0xf6, 0x4e, 0x7d, 0x56, 0x1e, 0x3a, 0xad,\r
+  0xfd, 0xbc, 0x5e, 0x1b, 0xc5, 0x5b, 0x86, 0xc9, 0xb6, 0x5b, 0xf5, 0xc3,\r
+  0x3e, 0xa6, 0x4e, 0xbb, 0x3e, 0x4b, 0xc6, 0x75, 0x19, 0xb1, 0x8d, 0x67,\r
+  0x52, 0x69, 0x5b, 0x8f, 0x17, 0x25, 0x59, 0xf9, 0xaf, 0x3b, 0x0c, 0x6b,\r
+  0x03, 0xf4, 0x71, 0xff, 0x0f, 0xa9, 0xd4, 0xa2, 0xea, 0x34, 0x64, 0x8c,\r
+  0xb9, 0x40, 0x7f, 0xce, 0xcf, 0x6b, 0xd2, 0x2e, 0xd7, 0xe4, 0x52, 0xe1,\r
+  0xf5, 0xce, 0x9a, 0x85, 0x55, 0x69, 0x2d, 0xc3, 0xda, 0x5f, 0x63, 0xb5,\r
+  0xd8, 0xe4, 0x7a, 0xb4, 0xa4, 0xe7, 0x6d, 0x56, 0xa9, 0x5a, 0x8d, 0x0e,\r
+  0xdc, 0xa6, 0xd7, 0x38, 0x84, 0x8d, 0x57, 0xe2, 0x56, 0x91, 0xfe, 0x1b,\r
+  0x0b, 0x2f, 0x5a, 0xc4, 0x73, 0x9d, 0xab, 0xd6, 0x88, 0xaf, 0xc1, 0x67,\r
+  0x59, 0xe8, 0x5b, 0xe0, 0x6b, 0xf6, 0x7d, 0xce, 0xf8, 0xb1, 0xf4, 0xb2,\r
+  0x2a, 0x15, 0x6b, 0xf9, 0x1d, 0x96, 0x57, 0x60, 0x1f, 0x6a, 0x8d, 0xfa,\r
+  0xee, 0xd6, 0xef, 0x73, 0xd2, 0xef, 0x3e, 0xae, 0xd4, 0xfe, 0xc7, 0x7e,\r
+  0x44, 0xf2, 0xd6, 0x2b, 0xfd, 0x08, 0x5e, 0x2a, 0xe4, 0xbb, 0x96, 0x05,\r
+  0x24, 0x8c, 0x80, 0x60, 0x2f, 0x5a, 0x23, 0xdf, 0x13, 0xed, 0xb7, 0xe1,\r
+  0xb9, 0xfa, 0x86, 0xae, 0x3e, 0xba, 0xd9, 0xca, 0xf9, 0x0b, 0x9a, 0x6b,\r
+  0x6a, 0x6a, 0xe9, 0x49, 0x2b, 0x8f, 0x35, 0xd4, 0xff, 0x98, 0x66, 0x1e,\r
+  0xb2, 0xea, 0xf1, 0x2c, 0xa0, 0xfb, 0xd2, 0xb2, 0x67, 0x35, 0x73, 0xc7,\r
+  0x9d, 0x62, 0xa2, 0xe7, 0xeb, 0x27, 0x3a, 0x96, 0x88, 0xa2, 0xe2, 0xdb,\r
+  0x0f, 0xd1, 0xdb, 0x56, 0x34, 0x16, 0x65, 0xf6, 0xaf, 0x3e, 0x8b, 0xae,\r
+  0xb6, 0x31, 0x4f, 0xd7, 0x49, 0xd2, 0x4c, 0x7f, 0xd6, 0xaa, 0xbe, 0xd5,\r
+  0x1d, 0x74, 0x97, 0x8d, 0x0a, 0xb6, 0xac, 0xde, 0xb7, 0x7a, 0xef, 0x05,\r
+  0x27, 0x4e, 0xd0, 0x2d, 0x36, 0x5d, 0x39, 0x3d, 0x0d, 0xf1, 0xa1, 0x2e,\r
+  0xb4, 0x61, 0xbf, 0x03, 0x2d, 0x7b, 0xfb, 0xbc, 0xcb, 0x77, 0x3e, 0xb5,\r
+  0x9a, 0x6e, 0x61, 0x5e, 0x78, 0x3c, 0x27, 0x9e, 0xa6, 0xfb, 0x1c, 0xd2,\r
+  0xf2, 0x4d, 0xba, 0xc9, 0x21, 0x8b, 0xfe, 0xc4, 0xce, 0xa4, 0x8f, 0x3e,\r
+  0xb0, 0xc0, 0x24, 0x4c, 0x1f, 0xa1, 0xbb, 0xfd, 0xc7, 0xf6, 0xfe, 0xa2,\r
+  0xf9, 0xad, 0xfe, 0x1a, 0x64, 0xd8, 0x4b, 0xaf, 0xb2, 0x9c, 0x5e, 0xb3,\r
+  0xb0, 0x95, 0xb1, 0x68, 0xb3, 0xd1, 0xb9, 0x87, 0xde, 0xe6, 0x21, 0xf9,\r
+  0x03, 0x3f, 0x8e, 0xf2, 0xeb, 0x9d, 0xef, 0xf1, 0xe3, 0x66, 0x83, 0xcd,\r
+  0xbe, 0xc3, 0xec, 0x0d, 0xfc, 0xf8, 0x3e, 0x3f, 0xfe, 0x81, 0x1f, 0x37,\r
+  0x19, 0xb2, 0x9e, 0x6f, 0x4b, 0x83, 0xef, 0xca, 0xe7, 0x8d, 0x4a, 0x74,\r
+  0x8b, 0x4c, 0x3c, 0xe1, 0xc0, 0xe3, 0x97, 0x3c, 0x8c, 0x87, 0x6b, 0x9a,\r
+  0xfb, 0x6e, 0x0b, 0xaf, 0x5e, 0x73, 0xa8, 0x96, 0x7e, 0xc7, 0x39, 0xdb,\r
+  0x58, 0xdd, 0xa6, 0x07, 0xab, 0xcd, 0xa6, 0x87, 0xef, 0x18, 0x4b, 0xef,\r
+  0xb5, 0xe3, 0x71, 0x39, 0xe7, 0x3f, 0x4c, 0x37, 0xca, 0xb6, 0xdd, 0x65,\r
+  0x78, 0xde, 0xaf, 0x5d, 0x1d, 0x32, 0x86, 0x3b, 0xb7, 0xd0, 0xcf, 0x2c,\r
+  0xb2, 0x8f, 0x4f, 0xbf, 0x79, 0xfb, 0xe1, 0xba, 0x90, 0x71, 0xfe, 0x10,\r
+  0x3d, 0x2e, 0x4d, 0xee, 0xa0, 0x47, 0x84, 0xa0, 0xce, 0x3b, 0x56, 0x1b,\r
+  0x67, 0x08, 0x5f, 0x81, 0x28, 0x29, 0x5a, 0x62, 0xe4, 0x8a, 0x39, 0x8a,\r
+  0x59, 0x2f, 0xca, 0x0a, 0x44, 0xb1, 0xfb, 0x8a, 0x9d, 0xc6, 0x6e, 0x70,\r
+  0xc6, 0x05, 0x62, 0x42, 0x01, 0x3d, 0xcc, 0xe5, 0xdf, 0x46, 0x6d, 0xb2,\r
+  0xb1, 0x6d, 0xb2, 0x48, 0x3a, 0x4b, 0x12, 0xe3, 0xb7, 0xd4, 0x64, 0xfc,\r
+  0xd1, 0xd8, 0x63, 0x7c, 0xdf, 0xb2, 0x67, 0xaf, 0x71, 0xf5, 0xbe, 0xd7,\r
+  0x0f, 0x47, 0x8e, 0x36, 0x37, 0x2f, 0x69, 0x6e, 0x5e, 0x7a, 0x7d, 0x4b,\r
+  0xf3, 0x5d, 0x46, 0x81, 0x98, 0x52, 0x60, 0xe4, 0x3f, 0x40, 0xdf, 0xc4,\r
+  0x18, 0x1d, 0xa5, 0xcb, 0x05, 0x55, 0xd3, 0xbb, 0xe8, 0xd0, 0x85, 0xab,\r
+  0x97, 0xd0, 0xf7, 0xd0, 0x82, 0x82, 0xa3, 0x4b, 0xe8, 0x10, 0x54, 0x17,\r
+  0x1e, 0xa2, 0x27, 0xed, 0x9c, 0xa4, 0x77, 0x98, 0x7c, 0x87, 0xae, 0x95,\r
+  0x4a, 0xfa, 0x4c, 0xce, 0xf6, 0x43, 0xf4, 0xbe, 0x4d, 0xf5, 0x7d, 0xc9,\r
+  0x21, 0xba, 0x86, 0x0d, 0x50, 0x6e, 0x49, 0x01, 0x3d, 0x00, 0x76, 0x33,\r
+  0x7d, 0x62, 0xc8, 0x86, 0x5c, 0xbc, 0xba, 0x59, 0xdd, 0xcf, 0x8a, 0x10,\r
+  0x81, 0xd9, 0xdf, 0x67, 0x92, 0xda, 0xe7, 0xa7, 0xc1, 0x9f, 0x27, 0xe9,\r
+  0x35, 0x20, 0x48, 0xd9, 0xa4, 0xdf, 0x67, 0x18, 0x19, 0xe4, 0xc9, 0x74,\r
+  0x9e, 0xb6, 0x49, 0xff, 0x1d, 0xd2, 0x3c, 0x4d, 0x6b, 0x35, 0x75, 0x6a,\r
+  0xfb, 0xe9, 0x3a, 0xff, 0x19, 0x5a, 0x5e, 0xad, 0xe5, 0xb5, 0x7a, 0x7d,\r
+  0x35, 0x62, 0x7f, 0x64, 0x79, 0x93, 0x6e, 0x83, 0x61, 0xaa, 0xaf, 0x09,\r
+  0xbb, 0x38, 0xf3, 0x9e, 0x4c, 0x5a, 0xc5, 0xed, 0x74, 0x9b, 0xac, 0x19,\r
+  0x5e, 0xbd, 0x0b, 0x4d, 0xdf, 0x35, 0x0d, 0xad, 0x33, 0xb4, 0xce, 0xd0,\r
+  0xeb, 0x59, 0x95, 0xef, 0x90, 0xe7, 0x27, 0x25, 0x6b, 0xd2, 0x74, 0x99,\r
+  0xa6, 0xad, 0xb2, 0x04, 0x8b, 0xd6, 0xe3, 0x26, 0x62, 0xaa, 0x47, 0xbd,\r
+  0x13, 0xb0, 0x48, 0xda, 0xaa, 0xc7, 0x46, 0xbd, 0x9b, 0x60, 0x9a, 0xa3,\r
+  0x69, 0xbe, 0xce, 0xeb, 0xc1, 0xd9, 0x55, 0x7e, 0x26, 0x61, 0x6a, 0x6b,\r
+  0x31, 0x7a, 0xcb, 0x29, 0xbb, 0x89, 0x4f, 0xf7, 0x25, 0x3d, 0xee, 0xd3,\r
+  0x34, 0x9d, 0x9e, 0x19, 0xbf, 0x56, 0x59, 0x4e, 0xad, 0x2c, 0x31, 0x3d,\r
+  0x76, 0xb5, 0x5a, 0xd6, 0x2a, 0x65, 0x56, 0x39, 0xfe, 0xa3, 0x65, 0x35,\r
+  0x6a, 0x59, 0xa3, 0xa9, 0xff, 0x8d, 0x32, 0xa5, 0xee, 0x9f, 0x4c, 0x5b,\r
+  0x49, 0xed, 0xc1, 0xad, 0xa6, 0x7c, 0x8c, 0xe5, 0x9a, 0xb6, 0xe9, 0xbe,\r
+  0xb2, 0xa6, 0xd0, 0xc4, 0x4f, 0xc9, 0xf8, 0xc5, 0x14, 0xd3, 0x18, 0x17,\r
+  0x66, 0xe6, 0xae, 0x4c, 0xeb, 0xdd, 0xba, 0xcc, 0xa9, 0xba, 0x9e, 0xda,\r
+  0x8c, 0xa5, 0x6a, 0x5b, 0x6d, 0xc6, 0x5a, 0xe4, 0x90, 0x70, 0x11, 0x2e,\r
+  0xc9, 0xa2, 0x9c, 0x8c, 0xf2, 0x4e, 0x12, 0x15, 0x64, 0x6f, 0x0e, 0x47,\r
+  0xc3, 0xa9, 0xa5, 0x64, 0x2c, 0x6d, 0x22, 0xeb, 0xd2, 0x26, 0x3c, 0xed,\r
+  0xfc, 0xac, 0xe8, 0xa5, 0xfc, 0xb6, 0xa1, 0x60, 0x74, 0x47, 0x68, 0x53,\r
+  0x30, 0x35, 0x30, 0x14, 0x4a, 0xd0, 0xc4, 0xb6, 0xd8, 0xae, 0x78, 0x2c,\r
+  0x1a, 0x8a, 0xa6, 0xba, 0x43, 0xa1, 0x44, 0x6f, 0x38, 0xb4, 0xa7, 0xf6,\r
+  0xbc, 0xe0, 0x48, 0x90, 0x5c, 0x6d, 0xb1, 0x68, 0x34, 0x34, 0x90, 0x0a,\r
+  0xc7, 0xa2, 0x24, 0x56, 0x92, 0xb1, 0xb2, 0x83, 0x44, 0x07, 0x19, 0x1d,\r
+  0x15, 0x40, 0x07, 0x59, 0x3a, 0x3a, 0x38, 0xd1, 0x09, 0xa6, 0xb3, 0x0b,\r
+  0x4c, 0x17, 0x89, 0x4e, 0x32, 0x3a, 0x19, 0x5d, 0x34, 0xbd, 0x73, 0x78,\r
+  0x20, 0xd4, 0x3a, 0x30, 0x10, 0x4a, 0x26, 0xc3, 0xdb, 0xc2, 0x91, 0x70,\r
+  0x6a, 0xdf, 0xda, 0xd8, 0x60, 0xa8, 0x3b, 0x11, 0x1b, 0x09, 0x0f, 0xa2,\r
+  0xc6, 0x92, 0xd5, 0xa1, 0x7d, 0xdb, 0x62, 0xc1, 0xc4, 0xe0, 0x8a, 0x70,\r
+  0x72, 0x57, 0x38, 0x99, 0xec, 0x0a, 0x27, 0x53, 0xa1, 0x28, 0x14, 0x02,\r
+  0x25, 0x75, 0xa1, 0xec, 0x2e, 0x2e, 0xbb, 0xab, 0x93, 0xac, 0x5d, 0x9d,\r
+  0x92, 0xeb, 0x82, 0x48, 0xca, 0x21, 0xc3, 0xa3, 0x8b, 0x26, 0x76, 0x05,\r
+  0xa3, 0x83, 0x89, 0x58, 0x78, 0xb0, 0x2e, 0x18, 0x8f, 0xd7, 0xb5, 0xa2,\r
+  0x91, 0x23, 0xa8, 0xa4, 0x89, 0xe6, 0x67, 0xcb, 0xe3, 0xf1, 0x48, 0x78,\r
+  0x20, 0xc8, 0x3d, 0x98, 0x9d, 0xb6, 0xe9, 0x0a, 0x6f, 0x0f, 0x0d, 0xec,\r
+  0x1b, 0x88, 0x84, 0xda, 0x82, 0x91, 0xc8, 0xb6, 0xe0, 0xc0, 0xce, 0x64,\r
+  0x13, 0x4d, 0x3e, 0x5d, 0x2e, 0xb3, 0x6a, 0x20, 0x16, 0x45, 0x23, 0x53,\r
+  0x75, 0x6d, 0x4c, 0xf7, 0xa6, 0xcc, 0xaa, 0x1d, 0x89, 0x60, 0x7c, 0x28,\r
+  0x3c, 0x90, 0xac, 0x6b, 0x0b, 0x46, 0x47, 0x82, 0x28, 0x70, 0xc6, 0x38,\r
+  0xaa, 0x58, 0x24, 0x96, 0x58, 0x19, 0x8e, 0xa4, 0x42, 0x89, 0xd3, 0xeb,\r
+  0xd7, 0x04, 0x53, 0x89, 0xf0, 0xde, 0x26, 0xaa, 0xf8, 0x5c, 0x7d, 0x56,\r
+  0x51, 0x93, 0xc6, 0x9a, 0x76, 0x07, 0xc3, 0xd1, 0xd4, 0xf8, 0x9a, 0x98,\r
+  0xd4, 0x94, 0x8c, 0xd5, 0x6c, 0xc0, 0x44, 0x37, 0xd1, 0x94, 0x8c, 0x22,\r
+  0x96, 0xac, 0x5b, 0x3e, 0x1c, 0x8e, 0x0c, 0xce, 0xee, 0x6d, 0xdf, 0xd0,\r
+  0xd3, 0xb1, 0x6e, 0x6d, 0x13, 0x15, 0x65, 0xeb, 0xa2, 0x83, 0x91, 0x50,\r
+  0x13, 0x15, 0x9b, 0x85, 0x1d, 0xcb, 0xc3, 0xd1, 0x41, 0x6e, 0xd3, 0x68,\r
+  0xf9, 0x3c, 0x52, 0x75, 0xed, 0x83, 0xe1, 0x54, 0x70, 0x1b, 0x9b, 0x4f,\r
+  0xca, 0x56, 0xf4, 0x84, 0x22, 0xca, 0xbf, 0xcc, 0x35, 0x2b, 0x4d, 0x3c,\r
+  0x18, 0xd5, 0xfe, 0x39, 0x36, 0x17, 0x74, 0x51, 0x55, 0xde, 0x19, 0xa7,\r
+  0xd1, 0xf4, 0x60, 0x98, 0xa2, 0x3b, 0x64, 0x07, 0xb8, 0x80, 0x53, 0x0a,\r
+  0x0f, 0xe0, 0x91, 0x29, 0x7c, 0xb4, 0x5b, 0xc3, 0xa9, 0x70, 0x84, 0xc7,\r
+  0x6e, 0x7c, 0x61, 0x33, 0x55, 0x66, 0x84, 0x23, 0x58, 0x23, 0x75, 0x6d,\r
+  0x43, 0xb1, 0x44, 0x28, 0x26, 0x07, 0x30, 0x94, 0x98, 0xbd, 0x32, 0x11,\r
+  0xdc, 0x95, 0x71, 0xa9, 0x26, 0x9a, 0xf6, 0x39, 0xb6, 0xe6, 0xf1, 0x91,\r
+  0x5a, 0xac, 0x86, 0xf6, 0x91, 0x50, 0x34, 0x6b, 0xfc, 0xa5, 0x62, 0x4d,\r
+  0x8c, 0x07, 0x47, 0xeb, 0x2a, 0xb2, 0x75, 0xbc, 0x4e, 0x67, 0xaf, 0x8b,\r
+  0xae, 0x8c, 0x0d, 0x0c, 0x27, 0xd5, 0x7a, 0x4e, 0xaf, 0x22, 0x73, 0xf3,\r
+  0x33, 0xa6, 0xe6, 0x51, 0xcc, 0x08, 0x57, 0x25, 0x62, 0xc3, 0xf1, 0x26,\r
+  0x5a, 0x38, 0x56, 0x13, 0x48, 0x84, 0x42, 0xeb, 0xb6, 0x25, 0x43, 0x89,\r
+  0x11, 0xf4, 0x6d, 0x5d, 0x74, 0x55, 0x24, 0xb6, 0x2d, 0x18, 0xe9, 0x0a,\r
+  0xee, 0x8b, 0x0d, 0xa7, 0x46, 0xab, 0x99, 0xf9, 0xf9, 0xf9, 0x9a, 0x68,\r
+  0x6e, 0xb6, 0x41, 0xd0, 0x1c, 0x10, 0xea, 0xb2, 0xc2, 0xc3, 0x9a, 0x60,\r
+  0x34, 0xb8, 0x83, 0xb3, 0xd4, 0x7f, 0xe9, 0x2c, 0x1c, 0x51, 0x3a, 0xa2,\r
+  0xdb, 0x63, 0x63, 0xda, 0xff, 0x05, 0x79, 0xd2, 0x51, 0xa8, 0x89, 0x6a,\r
+  0xb3, 0xf3, 0x85, 0xa3, 0xf1, 0xe1, 0xd4, 0xae, 0x50, 0x6a, 0x28, 0x36,\r
+  0x58, 0xb7, 0x3c, 0x98, 0x44, 0xe1, 0x48, 0x8f, 0xc6, 0x40, 0xb3, 0xb7,\r
+  0x8d, 0xb1, 0x67, 0x17, 0x8f, 0x25, 0x54, 0x73, 0x2a, 0x4f, 0x6f, 0x36,\r
+  0xa6, 0xc8, 0x9a, 0x2f, 0xb0, 0x5d, 0x23, 0xf9, 0xcc, 0xe8, 0xd4, 0x75,\r
+  0x0d, 0xc4, 0x76, 0xd5, 0x25, 0x76, 0x25, 0x23, 0x75, 0xe7, 0x21, 0xc2,\r
+  0xd6, 0x8d, 0x89, 0xdc, 0xb3, 0xb3, 0x42, 0x7b, 0x13, 0x55, 0x7f, 0x71,\r
+  0x06, 0x53, 0x6b, 0x96, 0x7d, 0xa1, 0xf5, 0xe7, 0xc6, 0xf5, 0x26, 0x5a,\r
+  0xf9, 0x85, 0x05, 0x9c, 0x26, 0xf2, 0xcf, 0xce, 0x76, 0x9c, 0xc6, 0xff,\r
+  0xd7, 0x72, 0xd8, 0xe7, 0xbe, 0x28, 0x2b, 0x2f, 0x7f, 0x39, 0xb8, 0x81,\r
+  0x60, 0x62, 0x47, 0x08, 0x2b, 0xab, 0xf4, 0x8b, 0xb2, 0x34, 0x51, 0x59,\r
+  0xd7, 0x60, 0x30, 0x32, 0x12, 0xde, 0x59, 0x87, 0x00, 0x13, 0x4b, 0xc9,\r
+  0xbd, 0xa1, 0xae, 0x3d, 0x3a, 0x10, 0x89, 0x25, 0x11, 0x67, 0xda, 0x22,\r
+  0xc1, 0xa4, 0x0c, 0xfa, 0x63, 0x6d, 0x3a, 0x30, 0xb8, 0x09, 0xad, 0x2f,\r
+  0x1d, 0x47, 0xbf, 0x26, 0xb4, 0x6b, 0x9b, 0x36, 0x08, 0xc1, 0x64, 0xfa,\r
+  0x38, 0x26, 0x3d, 0xe1, 0x1d, 0xd1, 0x60, 0x6a, 0x38, 0x21, 0xc3, 0x27,\r
+  0x6f, 0xcc, 0x75, 0x11, 0x4c, 0x31, 0x42, 0x4a, 0x30, 0xd1, 0x13, 0xda,\r
+  0x3d, 0x1c, 0x8a, 0x0e, 0x40, 0xe3, 0x31, 0x6b, 0x54, 0x75, 0x65, 0x26,\r
+  0x51, 0x47, 0x24, 0x12, 0xda, 0x11, 0x8c, 0xa8, 0x99, 0x6b, 0xdf, 0x3b,\r
+  0x10, 0x8a, 0xab, 0x09, 0x9f, 0x3d, 0x8e, 0x4d, 0x62, 0xc7, 0xf0, 0x2e,\r
+  0xf4, 0xdd, 0x64, 0x55, 0x64, 0xb6, 0xc2, 0xe6, 0x27, 0x5d, 0xb1, 0xd4,\r
+  0x24, 0x5c, 0x1b, 0xeb, 0x19, 0x1e, 0x18, 0x52, 0xbe, 0x6a, 0xca, 0xe7,\r
+  0x35, 0x99, 0xac, 0xdb, 0x76, 0x9e, 0xdc, 0x61, 0xa6, 0x9b, 0x64, 0x3d,\r
+  0xa1, 0x81, 0xe1, 0x04, 0x7c, 0xe8, 0x34, 0x59, 0x54, 0x10, 0xe7, 0x35,\r
+  0x32, 0x2a, 0x4b, 0x84, 0xb6, 0xf3, 0x96, 0x81, 0x66, 0x8c, 0xc4, 0xd4,\r
+  0x16, 0xad, 0x26, 0xd1, 0x54, 0xc4, 0x94, 0x71, 0xcc, 0x55, 0xd3, 0x9a,\r
+  0x68, 0x82, 0xd2, 0xc9, 0xa0, 0xde, 0x9a, 0x48, 0x04, 0xf7, 0xb1, 0xdf,\r
+  0x34, 0x91, 0xdb, 0x24, 0x1e, 0x5f, 0xd2, 0x4c, 0x8e, 0x9e, 0x15, 0xab,\r
+  0xcf, 0xed, 0x58, 0x1b, 0x20, 0x6b, 0x60, 0x73, 0x77, 0x3b, 0x15, 0x9e,\r
+  0xe2, 0x45, 0x94, 0x67, 0xf6, 0x60, 0x12, 0xbd, 0x64, 0xf4, 0xe2, 0xc0,\r
+  0xd2, 0x8b, 0xe3, 0x8b, 0xb5, 0x97, 0x8f, 0x4a, 0x36, 0x7e, 0xe2, 0x2c,\r
+  0xd3, 0xdb, 0x49, 0xf6, 0xde, 0xce, 0x8e, 0x95, 0x2b, 0x71, 0xba, 0xe9,\r
+  0xed, 0x94, 0x8a, 0x4e, 0x56, 0x58, 0x7a, 0x71, 0x76, 0xc2, 0xa3, 0x8b,\r
+  0xc5, 0x7c, 0xe0, 0xe9, 0xed, 0xec, 0x83, 0x35, 0x33, 0x5d, 0x5c, 0x46,\r
+  0x97, 0x34, 0xed, 0x52, 0xa6, 0x7c, 0x0c, 0xea, 0x85, 0x11, 0x04, 0x2c,\r
+  0x77, 0x48, 0x22, 0xab, 0xea, 0x92, 0x59, 0x71, 0x2b, 0x06, 0xdb, 0xd7,\r
+  0x29, 0x9f, 0x38, 0x53, 0xf5, 0xf6, 0xa1, 0xd2, 0x3e, 0x69, 0x22, 0xfa,\r
+  0xc8, 0xd2, 0xc7, 0xa6, 0x78, 0x74, 0x31, 0x0b, 0x35, 0x0c, 0x6d, 0x7d,\r
+  0x9d, 0x9c, 0xb6, 0x82, 0xb0, 0x80, 0x35, 0xa8, 0xd6, 0xde, 0xd7, 0x25,\r
+  0xc5, 0x36, 0xa6, 0x90, 0xf7, 0xe3, 0x18, 0xd8, 0xdf, 0x41, 0xde, 0xfe,\r
+  0xb1, 0xee, 0x56, 0xd4, 0x3f, 0xce, 0x6c, 0xbb, 0x54, 0x2c, 0x9e, 0xed,\r
+  0xf7, 0xfb, 0x33, 0xfc, 0x5c, 0xf0, 0xb9, 0xa3, 0xbc, 0x29, 0x91, 0xa5,\r
+  0xa9, 0x37, 0x27, 0xe6, 0x99, 0x13, 0xf3, 0xcd, 0x89, 0x05, 0xe6, 0xc4,\r
+  0x42, 0x73, 0x62, 0x91, 0x39, 0xd1, 0x60, 0x4e, 0x34, 0x9a, 0x5a, 0x53,\r
+  0x6f, 0xe2, 0xe7, 0x99, 0xf8, 0xf9, 0x26, 0x7e, 0x81, 0x89, 0x5f, 0x68,\r
+  0xe2, 0x17, 0x99, 0xf8, 0x06, 0x13, 0xdf, 0x38, 0x5a, 0xd9, 0xca, 0x48,\r
+  0x70, 0x47, 0x92, 0xf2, 0xb3, 0xb6, 0x24, 0x2a, 0x0e, 0x8e, 0xb3, 0xf5,\r
+  0x71, 0x0e, 0x76, 0xe0, 0xae, 0xe0, 0xb6, 0x50, 0x84, 0x2c, 0xc1, 0xc1,\r
+  0x41, 0x9a, 0x8c, 0xc7, 0xf8, 0x7b, 0x2f, 0xb9, 0x83, 0xdb, 0x71, 0xfa,\r
+  0x63, 0x1f, 0x54, 0x01, 0x7f, 0x90, 0x3c, 0x7c, 0xf0, 0x58, 0x3e, 0x9c,\r
+  0x4a, 0xc5, 0xa2, 0xdd, 0x09, 0x94, 0x2e, 0x45, 0xa1, 0xed, 0x38, 0x77,\r
+  0x98, 0xad, 0xec, 0xdb, 0x62, 0xb0, 0xd8, 0x45, 0xf6, 0x81, 0x20, 0x36,\r
+  0x88, 0x41, 0x72, 0x2b, 0x6a, 0x3a, 0xe9, 0xe7, 0x0f, 0x64, 0x5d, 0x0e,\r
+  0x6c, 0x38, 0x29, 0x07, 0x13, 0x54, 0xc8, 0xa1, 0x2e, 0x64, 0x32, 0x2b,\r
+  0x91, 0x02, 0xd3, 0x1e, 0xa5, 0x8f, 0xc5, 0x94, 0x3b, 0xc0, 0x3b, 0x02,\r
+  0x9f, 0x33, 0x5b, 0x53, 0x54, 0x90, 0x49, 0xb4, 0xc5, 0x86, 0xa3, 0x29,\r
+  0x14, 0x0e, 0x2b, 0x9c, 0x4e, 0x93, 0x52, 0x46, 0xc5, 0xfa, 0x4c, 0x9d,\r
+  0x5c, 0x2e, 0x1b, 0xaa, 0x1a, 0x49, 0x53, 0x07, 0x12, 0xa1, 0x60, 0x6a,\r
+  0xec, 0x36, 0xc3, 0xbb, 0x2b, 0x39, 0x06, 0x63, 0xf2, 0xa8, 0x45, 0xce,\r
+  0x90, 0x3e, 0x55, 0x82, 0x8b, 0x0e, 0x26, 0x37, 0x85, 0x53, 0x43, 0xe4,\r
+  0xdb, 0x8e, 0x03, 0xe8, 0xb8, 0xf9, 0x92, 0xcb, 0xf7, 0xf1, 0x30, 0x50,\r
+  0x0e, 0x5b, 0xc8, 0x33, 0x13, 0xe5, 0x6d, 0x1f, 0x3d, 0x3a, 0x0d, 0xd2,\r
+  0x54, 0xac, 0xe1, 0xac, 0x9c, 0xd2, 0x88, 0x83, 0x7f, 0xc7, 0x20, 0x4d,\r
+  0x3b, 0x55, 0x99, 0x75, 0x9b, 0xc9, 0x91, 0x5a, 0x39, 0x2a, 0x85, 0x19,\r
+  0x76, 0x4d, 0x30, 0xb9, 0x13, 0xc5, 0x4e, 0x60, 0xc1, 0xe8, 0x7d, 0x22,\r
+  0x3d, 0x48, 0x6e, 0x88, 0xdb, 0x82, 0x89, 0x50, 0xaa, 0x1b, 0x1b, 0x88,\r
+  0xcc, 0x59, 0xcc, 0x12, 0x84, 0xf4, 0x0e, 0x9c, 0xa0, 0xf7, 0xae, 0x8c,\r
+  0x25, 0xd4, 0x00, 0xe5, 0x6b, 0x29, 0x5c, 0x23, 0x94, 0x48, 0x92, 0x93,\r
+  0x93, 0xbc, 0xdc, 0xa8, 0x88, 0x39, 0xde, 0xa6, 0x78, 0xff, 0xe1, 0x63,\r
+  0x6f, 0x7b, 0x54, 0x55, 0x96, 0x25, 0xec, 0x49, 0x05, 0x13, 0x29, 0x72,\r
+  0x49, 0xb1, 0x9e, 0x1d, 0x8e, 0x95, 0xe9, 0x81, 0xcb, 0xe3, 0x04, 0x1f,\r
+  0x2e, 0x03, 0x61, 0x0c, 0xe8, 0x64, 0xa4, 0x64, 0xa7, 0x43, 0x83, 0xa7,\r
+  0xc6, 0x36, 0xdf, 0x69, 0x55, 0xb2, 0x99, 0x7a, 0x0c, 0xce, 0x0a, 0x85,\r
+  0x77, 0x0c, 0xa5, 0x64, 0x39, 0x67, 0x81, 0x8b, 0x70, 0x2a, 0x34, 0xb8,\r
+  0x21, 0xb4, 0x03, 0xfd, 0x5b, 0x8e, 0x27, 0x9c, 0x66, 0x3c, 0x15, 0xb7,\r
+  0x9c, 0xbb, 0x23, 0x4b, 0x35, 0x8f, 0xfa, 0x84, 0xb4, 0x30, 0xeb, 0x10,\r
+  0x44, 0x67, 0xa6, 0xc5, 0x81, 0x7d, 0xf1, 0x10, 0x46, 0x8a, 0x8f, 0x24,\r
+  0xbd, 0xe1, 0x44, 0x6a, 0x38, 0x18, 0x49, 0x1f, 0x0a, 0x58, 0x23, 0xbb,\r
+  0xda, 0x11, 0x4d, 0xa6, 0x82, 0xd8, 0x20, 0xe5, 0xc4, 0x64, 0x69, 0xb9,\r
+  0xc6, 0x2e, 0xbd, 0x85, 0xac, 0x8b, 0xf6, 0xc0, 0xe5, 0x42, 0x51, 0x39,\r
+  0x20, 0xa8, 0x2c, 0x88, 0x71, 0x4b, 0x85, 0x64, 0x9f, 0x54, 0xd5, 0x32,\r
+  0xbb, 0xee, 0xaa, 0x72, 0xe4, 0xbc, 0x51, 0x01, 0x5a, 0xea, 0x40, 0x6a,\r
+  0x43, 0x70, 0xcf, 0xd9, 0x69, 0x66, 0xb3, 0xac, 0x7c, 0x43, 0x2c, 0x96,\r
+  0xe2, 0xae, 0xc8, 0xdc, 0x99, 0xab, 0x0e, 0x77, 0xd7, 0x63, 0x16, 0xa8,\r
+  0x49, 0x62, 0x8f, 0xe8, 0xd9, 0x87, 0xd5, 0xbd, 0xab, 0x07, 0x3b, 0x48,\r
+  0x18, 0x4d, 0x2e, 0x80, 0x44, 0x8d, 0xf6, 0x06, 0xb9, 0x2c, 0xd8, 0x22,\r
+  0x80, 0x43, 0x41, 0x64, 0xed, 0xf0, 0x2e, 0xf6, 0x09, 0xe5, 0x04, 0x1b,\r
+  0xf9, 0xc6, 0x15, 0x09, 0x47, 0x31, 0x9a, 0x6c, 0x95, 0x94, 0xd9, 0x36,\r
+  0x46, 0xc3, 0xbc, 0xf0, 0xd8, 0x4a, 0x1a, 0x9d, 0x7a, 0x32, 0x97, 0x7e,\r
+  0xd5, 0x1b, 0xce, 0x04, 0x24, 0xce, 0xb3, 0x09, 0x0b, 0x23, 0xb6, 0x27,\r
+  0x10, 0xdb, 0x89, 0x71, 0x98, 0x96, 0x49, 0x4b, 0xa3, 0x48, 0x08, 0xa7,\r
+  0xac, 0x78, 0x24, 0xb8, 0x4f, 0xad, 0x3c, 0x2b, 0xb4, 0x67, 0xcb, 0xe7,\r
+  0x66, 0x9a, 0x84, 0xe5, 0x83, 0x8b, 0x60, 0xd6, 0xe2, 0x38, 0x2b, 0xc6,\r
+  0x55, 0x14, 0x6a, 0x4d, 0x3c, 0xde, 0x1d, 0x64, 0xc7, 0x21, 0x77, 0x46,\r
+  0xb0, 0x21, 0x94, 0xc4, 0x11, 0x23, 0x23, 0x59, 0x9e, 0x09, 0x5c, 0x94,\r
+  0xaf, 0x24, 0x2b, 0xf4, 0x1a, 0xd7, 0x49, 0x4c, 0xdc, 0x8a, 0xd8, 0x9e,\r
+  0x28, 0xe5, 0x66, 0x92, 0x1b, 0xe3, 0x54, 0x9c, 0x49, 0xc8, 0x49, 0x3d,\r
+  0x2b, 0x3c, 0x38, 0x88, 0x96, 0xeb, 0x5a, 0xd7, 0xc4, 0x50, 0xa5, 0xcc,\r
+  0x93, 0x25, 0x48, 0x04, 0x77, 0xa4, 0xcb, 0x94, 0x02, 0x14, 0xa3, 0xcb,\r
+  0x94, 0x57, 0x66, 0x2a, 0xd2, 0x89, 0x50, 0x02, 0xe1, 0x68, 0x97, 0x5e,\r
+  0xd3, 0x79, 0x43, 0x58, 0xe5, 0xe9, 0x6a, 0xa8, 0x84, 0x53, 0x3d, 0xb1,\r
+  0xed, 0xda, 0x5d, 0x13, 0xb1, 0x5d, 0x6a, 0xa0, 0xc8, 0x39, 0x84, 0x12,\r
+  0x64, 0x8c, 0xb1, 0x0e, 0xc5, 0x92, 0x58, 0x75, 0x58, 0x53, 0xeb, 0xe4,\r
+  0x91, 0x24, 0x49, 0x85, 0xfc, 0x26, 0x26, 0x1c, 0x8c, 0xb4, 0x05, 0xe3,\r
+  0xc9, 0x35, 0x98, 0x18, 0xca, 0xd7, 0x02, 0x38, 0x01, 0xfb, 0x43, 0xe1,\r
+  0x68, 0x52, 0x79, 0x43, 0x4e, 0x38, 0xed, 0xe0, 0x94, 0x27, 0xd9, 0x73,\r
+  0xd5, 0xa5, 0x80, 0x3c, 0x88, 0x9d, 0xa1, 0x84, 0xac, 0xa7, 0x55, 0x45,\r
+  0x10, 0x72, 0xa2, 0xde, 0xde, 0x60, 0x64, 0x38, 0x44, 0xf6, 0x30, 0x4e,\r
+  0x45, 0x3b, 0x43, 0xa8, 0x3a, 0x99, 0x71, 0x7c, 0x67, 0x38, 0xb9, 0x2e,\r
+  0x1e, 0xc4, 0x31, 0x11, 0x59, 0x93, 0x99, 0xc5, 0x2b, 0x5f, 0x86, 0x60,\r
+  0xc9, 0x43, 0x14, 0xc3, 0xc9, 0xad, 0x7d, 0x6f, 0x3c, 0x12, 0x4b, 0x04,\r
+  0x95, 0x7b, 0x72, 0x68, 0x18, 0x44, 0x0b, 0x92, 0x7a, 0xee, 0xa9, 0x64,\r
+  0xe7, 0x69, 0xde, 0xd6, 0xe4, 0xa7, 0x15, 0x3d, 0x43, 0x3c, 0xd4, 0xb6,\r
+  0x88, 0xdc, 0xba, 0xec, 0x91, 0x50, 0x74, 0x07, 0x82, 0xb1, 0x35, 0xca,\r
+  0x53, 0x98, 0x17, 0x35, 0x87, 0x4a, 0x7b, 0x6c, 0x1b, 0x87, 0x7f, 0xf2,\r
+  0xc6, 0xb6, 0x6f, 0x4f, 0x86, 0x52, 0xcb, 0xf7, 0xb5, 0xa5, 0xf7, 0x87,\r
+  0x24, 0x79, 0x62, 0xd1, 0xf4, 0x3b, 0x9a, 0x36, 0xb9, 0x01, 0x20, 0x2c,\r
+  0x8c, 0x8a, 0x56, 0x84, 0x92, 0xa9, 0x44, 0x6c, 0x1f, 0x7b, 0xcd, 0xa8,\r
+  0x50, 0x7b, 0x96, 0x29, 0x67, 0xda, 0xb5, 0xa6, 0x8e, 0x8a, 0x7a, 0x82,\r
+  0x23, 0xa1, 0xf4, 0x70, 0xa8, 0x85, 0x6d, 0xb2, 0x97, 0xc3, 0x9d, 0x5d,\r
+  0x44, 0x4f, 0x2a, 0x16, 0x8f, 0x43, 0x54, 0x82, 0x70, 0x2d, 0xdb, 0x71,\r
+  0xca, 0xa5, 0x0d, 0x9d, 0x88, 0xc2, 0x93, 0xf6, 0x50, 0x7e, 0xcc, 0x7c,\r
+  0xfb, 0xa6, 0x82, 0x58, 0xd6, 0x56, 0x4d, 0x79, 0xb1, 0xa8, 0x5c, 0x09,\r
+  0x32, 0xc2, 0x52, 0x4e, 0x2c, 0x9a, 0x76, 0xe3, 0x7c, 0xc9, 0xae, 0x19,\r
+  0x8e, 0xa4, 0xc2, 0x71, 0x0c, 0xaf, 0x43, 0x26, 0xe1, 0x8a, 0x4e, 0xde,\r
+  0xfc, 0x65, 0x56, 0x58, 0xf4, 0x84, 0xcf, 0x0f, 0xa5, 0xf7, 0xa6, 0x5c,\r
+  0x24, 0x11, 0xcd, 0x5b, 0xe1, 0xe1, 0x83, 0x52, 0x87, 0x44, 0x5a, 0xa7,\r
+  0x93, 0x1b, 0x42, 0xbb, 0x50, 0x97, 0x4c, 0x9a, 0xb7, 0x7b, 0xb4, 0x41,\r
+  0x4d, 0xb0, 0x6c, 0x83, 0x3d, 0xa6, 0x3c, 0xc1, 0x16, 0x97, 0xde, 0x9e,\r
+  0x1f, 0xcf, 0xf2, 0xf3, 0xe9, 0xf1, 0x58, 0x7c, 0x38, 0x72, 0xda, 0x8d,\r
+  0xd7, 0x83, 0x6d, 0x25, 0x95, 0xf5, 0x96, 0x83, 0x1c, 0x09, 0xf5, 0x26,\r
+  0x8d, 0xca, 0x12, 0x88, 0xe4, 0x70, 0x8a, 0xc4, 0xe9, 0x5f, 0xb2, 0xd1,\r
+  0xb4, 0x84, 0x6c, 0xe2, 0x69, 0xce, 0x33, 0x2e, 0xa5, 0xe5, 0xae, 0x50,\r
+  0x1e, 0x8e, 0x2f, 0x3c, 0x2d, 0x72, 0xdc, 0xc9, 0x02, 0x3f, 0xa1, 0x82,\r
+  0x24, 0x6f, 0x61, 0x99, 0xb7, 0x5e, 0x94, 0x97, 0xd4, 0x1b, 0x92, 0xdc,\r
+  0xc7, 0x4a, 0xcc, 0xa9, 0x0e, 0xd5, 0x63, 0xb9, 0xcc, 0x8a, 0x93, 0xe3,\r
+  0xec, 0x37, 0x32, 0x33, 0xaa, 0xc7, 0xf1, 0x89, 0xd7, 0xd7, 0x24, 0xa4,\r
+  0xc6, 0x7d, 0x8d, 0x22, 0xed, 0x32, 0x51, 0x9a, 0x1c, 0x9c, 0xe2, 0xe6,\r
+  0x4d, 0x48, 0xa6, 0x23, 0xf5, 0xc6, 0xb0, 0x29, 0x86, 0x4e, 0x1d, 0x57,\r
+  0xcc, 0xdb, 0x71, 0x30, 0x25, 0x5b, 0x18, 0x08, 0x61, 0x67, 0x4e, 0x04,\r
+  0x13, 0xfb, 0xd2, 0x21, 0x1b, 0x9b, 0x34, 0xe5, 0x26, 0x55, 0x74, 0x5e,\r
+  0x2b, 0xc3, 0x5d, 0x32, 0x2b, 0x2a, 0xbb, 0xd2, 0x49, 0x74, 0x91, 0x07,\r
+  0x60, 0x53, 0x38, 0x12, 0x59, 0x1b, 0x4b, 0x49, 0xdf, 0xcb, 0x4b, 0x62,\r
+  0xc9, 0x65, 0x82, 0x52, 0x3e, 0xa7, 0x32, 0x41, 0x09, 0xc6, 0x3c, 0x7c,\r
+  0xaa, 0x1f, 0x5c, 0x49, 0x7e, 0x12, 0x2e, 0x3d, 0x9a, 0xcc, 0x4d, 0x0e,\r
+  0x6f, 0x4b, 0xdf, 0x1c, 0x29, 0x07, 0x89, 0xa4, 0xbc, 0x68, 0x91, 0x3d,\r
+  0xa5, 0x76, 0xfb, 0x99, 0xa9, 0xec, 0x3d, 0x7e, 0xd5, 0xa9, 0x67, 0x95,\r
+  0x59, 0xe3, 0x18, 0x8c, 0x39, 0xba, 0x94, 0x8f, 0x35, 0x3a, 0xcd, 0xa9,\r
+  0xe0, 0xcc, 0x2f, 0x61, 0xc9, 0x51, 0x72, 0xc6, 0x58, 0xbb, 0xac, 0x2d,\r
+  0x7d, 0xfa, 0x58, 0xbd, 0x79, 0xff, 0x1c, 0xa7, 0x5b, 0xd9, 0xdb, 0xa9,\r
+  0xef, 0x14, 0x83, 0x8e, 0x31, 0xa1, 0x76, 0x8c, 0xc5, 0x98, 0x88, 0x7a,\r
+  0xea, 0xd0, 0xf4, 0x8c, 0xe7, 0x80, 0xa7, 0x76, 0xb8, 0xe7, 0x34, 0xce,\r
+  0x61, 0x4f, 0x0d, 0x85, 0x71, 0x77, 0xd2, 0x74, 0x2e, 0x39, 0x53, 0x31,\r
+  0x75, 0x27, 0x26, 0x0b, 0x26, 0x94, 0x4a, 0x87, 0xe3, 0x83, 0x58, 0xae,\r
+  0xe9, 0xe3, 0x5c, 0xc6, 0x55, 0x79, 0x53, 0xd2, 0x07, 0xb7, 0x0a, 0x65,\r
+  0xa2, 0x52, 0xfa, 0x68, 0xc8, 0x26, 0xea, 0xac, 0xc0, 0x86, 0x99, 0xc3,\r
+  0xe0, 0x0c, 0xb3, 0xe9, 0x38, 0xfa, 0x52, 0xb3, 0x3e, 0xab, 0xae, 0x8c,\r
+  0x89, 0x6d, 0x44, 0x6e, 0x43, 0x0e, 0x49, 0xd6, 0x6d, 0x27, 0xeb, 0x88,\r
+  0x3c, 0xfd, 0xf0, 0xd3, 0x1c, 0xce, 0xdc, 0x23, 0xa7, 0x1e, 0x47, 0x12,\r
+  0x17, 0x5f, 0xbc, 0xa2, 0xe1, 0x82, 0x32, 0x0e, 0x14, 0x38, 0xcb, 0x97,\r
+  0x2d, 0x2e, 0x83, 0x23, 0x95, 0x55, 0x97, 0x0d, 0xa0, 0xc1, 0xe1, 0x88,\r
+  0xdc, 0x96, 0x6a, 0x76, 0x61, 0x3d, 0x43, 0x91, 0x40, 0xc5, 0xc1, 0x64,\r
+  0x08, 0xca, 0xa1, 0x60, 0xb2, 0x06, 0x37, 0x14, 0x84, 0x96, 0xe1, 0x5d,\r
+  0xc9, 0xb2, 0xc5, 0xdb, 0x83, 0x91, 0x64, 0xa8, 0xba, 0x6c, 0x57, 0x38,\r
+  0x5a, 0x13, 0x8c, 0x87, 0xcb, 0x16, 0xcf, 0x5d, 0x58, 0x5d, 0x86, 0xa2,\r
+  0x93, 0xc8, 0x8b, 0x6c, 0xf3, 0x6a, 0xe7, 0xd5, 0xd6, 0xfb, 0x6b, 0x06,\r
+  0x43, 0x23, 0x55, 0xc1, 0x58, 0x32, 0xbe, 0xa0, 0xec, 0x22, 0x32, 0xea,\r
+  0xc5, 0x6b, 0xc6, 0x34, 0x67, 0x89, 0xb5, 0x64, 0x5e, 0x89, 0xbd, 0x64,\r
+  0xa0, 0x64, 0x71, 0x49, 0x1f, 0x7e, 0x73, 0x8c, 0x3a, 0x88, 0x27, 0xd5,\r
+  0x1a, 0x7e, 0xe3, 0x76, 0x61, 0x9d, 0x72, 0x8d, 0x51, 0x92, 0x3b, 0xca,\r
+  0xe6, 0xab, 0x3c, 0x76, 0xe4, 0x39, 0xa7, 0xc4, 0x83, 0x3c, 0xed, 0x25,\r
+  0x4e, 0xa5, 0xf5, 0x42, 0x3b, 0x45, 0x65, 0xad, 0x56, 0x12, 0x03, 0x92,\r
+  0x1d, 0xa3, 0xca, 0xa9, 0xc6, 0x5c, 0xce, 0x2a, 0x26, 0x55, 0x8d, 0x96,\r
+  0x91, 0xae, 0xd3, 0xa5, 0xcc, 0x72, 0x60, 0xb6, 0x3d, 0xad, 0xb5, 0x99,\r
+  0xb4, 0x32, 0xa7, 0x6d, 0x52, 0xe5, 0xa4, 0x8a, 0x49, 0xe5, 0x93, 0xaa,\r
+  0x27, 0xd5, 0x90, 0xd5, 0x6e, 0xcf, 0x35, 0x84, 0x97, 0x7f, 0x17, 0x5e,\r
+  0xb2, 0xdf, 0x7a, 0xb2, 0xc2, 0xe2, 0x7a, 0xab, 0xdc, 0xe6, 0xda, 0x5f,\r
+  0x23, 0x5c, 0x2f, 0x00, 0xef, 0x02, 0x57, 0xd6, 0x2e, 0x12, 0x07, 0x2b,\r
+  0x85, 0x38, 0x5a, 0x69, 0x88, 0x87, 0x41, 0x4f, 0x02, 0x1f, 0x73, 0xba,\r
+  0x8a, 0xac, 0xc2, 0x28, 0x34, 0x84, 0xfc, 0x5d, 0xbe, 0x7f, 0xbf, 0xf5,\r
+  0xf5, 0xba, 0x36, 0xb1, 0xdf, 0x0f, 0x8b, 0x5a, 0x32, 0x84, 0xb5, 0xe8,\r
+  0x88, 0x4f, 0x78, 0xdb, 0x51, 0xe8, 0x91, 0x79, 0x2b, 0xc5, 0xc3, 0x10,\r
+  0x7f, 0x58, 0x2f, 0xc4, 0xc3, 0x73, 0x85, 0xb8, 0xbb, 0x1e, 0x6a, 0x31,\r
+  0xc1, 0x10, 0x47, 0x7c, 0x9d, 0xc8, 0x75, 0x7c, 0xde, 0x6a, 0xf1, 0xca,\r
+  0x3c, 0xb2, 0xd8, 0xa9, 0x84, 0x73, 0x08, 0x6f, 0x17, 0xf2, 0xdc, 0xb9,\r
+  0x40, 0x1c, 0xf6, 0x9d, 0xe4, 0xc7, 0x07, 0xfc, 0x38, 0xb2, 0x40, 0x18,\r
+  0x87, 0x17, 0x0a, 0xe3, 0xf8, 0x42, 0x12, 0x22, 0x77, 0x8a, 0x77, 0x03,\r
+  0xb7, 0xb5, 0xa1, 0x47, 0x7c, 0xbc, 0x10, 0xed, 0x58, 0x84, 0x62, 0x81,\r
+  0x93, 0xc0, 0xc7, 0xcc, 0x37, 0x40, 0x06, 0x7c, 0x08, 0x9c, 0x84, 0xfe,\r
+  0x48, 0x23, 0xaa, 0x6c, 0x24, 0x47, 0xfd, 0xcc, 0xa9, 0x5e, 0xd9, 0x56,\r
+  0xaf, 0xfa, 0x3d, 0x07, 0x65, 0xbc, 0xb0, 0x0a, 0x85, 0x1f, 0x6d, 0xc2,\r
+  0xe3, 0x85, 0x15, 0x78, 0xec, 0x5f, 0x8d, 0xc7, 0x09, 0x29, 0x93, 0x1c,\r
+  0x2b, 0x5e, 0x5f, 0x89, 0xc7, 0xa7, 0xfc, 0x78, 0x89, 0x93, 0xbf, 0x67,\r
+  0xbb, 0xe3, 0xac, 0x3d, 0xca, 0x76, 0xcf, 0x32, 0x77, 0xb0, 0x1d, 0x8f,\r
+  0x9b, 0xf9, 0xf1, 0x18, 0x3f, 0x4e, 0xb6, 0xdb, 0x0f, 0x18, 0x24, 0x00,\r
+  0x8b, 0x71, 0x74, 0x05, 0x53, 0x83, 0xe1, 0xfa, 0xb0, 0xdd, 0xa1, 0xe5,\r
+  0x7f, 0x0f, 0x26, 0x00, 0xae, 0xcb, 0xc1, 0x7f, 0x59, 0xc0, 0x3e, 0x2e,\r
+  0x5e, 0x5f, 0x2d, 0xc4, 0x95, 0x5d, 0x42, 0xdc, 0x09, 0xbc, 0xdb, 0x24,\r
+  0xc4, 0xab, 0x5d, 0x16, 0xf1, 0x6c, 0xa3, 0x9d, 0xde, 0x5d, 0x3c, 0x41,\r
+  0x5c, 0xb7, 0x46, 0x88, 0xfd, 0xcd, 0x18, 0x24, 0xe0, 0x25, 0xf0, 0x6f,\r
+  0x01, 0x1f, 0x03, 0xb7, 0xae, 0x45, 0x1a, 0x78, 0x0b, 0xf8, 0x18, 0x78,\r
+  0x1d, 0x03, 0x77, 0xe5, 0x3a, 0x21, 0x1e, 0x63, 0xc0, 0xf6, 0xc8, 0x12,\r
+  0x21, 0x0e, 0x2e, 0x15, 0xe2, 0xba, 0x65, 0xc2, 0xfa, 0xee, 0x3a, 0x61,\r
+  0xdd, 0xdf, 0x2d, 0xc4, 0x0b, 0xcb, 0x6c, 0xe2, 0x38, 0xe8, 0xad, 0xeb,\r
+  0xe1, 0x1c, 0xc0, 0xab, 0xeb, 0x49, 0xfd, 0xf0, 0x67, 0x8d, 0x81, 0x55,\r
+  0xea, 0xb3, 0xc7, 0x9d, 0xa0, 0x09, 0x13, 0x7f, 0xd1, 0x2a, 0xa5, 0x3f,\r
+  0x6c, 0x92, 0xdd, 0xa8, 0xf9, 0xdb, 0x41, 0xef, 0x59, 0xa5, 0x3e, 0xdf,\r
+  0x64, 0xf9, 0xc3, 0xc0, 0x4f, 0xb5, 0xfd, 0x0b, 0x26, 0xfb, 0xd7, 0xb4,\r
+  0xec, 0x0f, 0x9a, 0xfe, 0x0d, 0x34, 0xde, 0x39, 0x5a, 0x37, 0xe9, 0xcf,\r
+  0x5d, 0x87, 0x20, 0xbb, 0x50, 0xcb, 0xd3, 0x3f, 0x47, 0x4e, 0xb1, 0xe3,\r
+  0xef, 0x1f, 0x39, 0x0c, 0xd9, 0x4d, 0xa7, 0xd8, 0xdd, 0x79, 0x4a, 0xfa,\r
+  0x89, 0x53, 0xf2, 0xf1, 0xf7, 0x8b, 0x3c, 0x0c, 0xd9, 0x2b, 0xa7, 0xc8,\r
+  0xf9, 0xff, 0x06, 0xbf, 0xd0, 0x39, 0xfa, 0xbd, 0x1c, 0xc2, 0x44, 0xd3,\r
+  0xdf, 0xa3, 0xc5, 0xfd, 0x48, 0x7f, 0x97, 0x16, 0xf7, 0x35, 0xfd, 0x7d,\r
+  0x5a, 0xfc, 0x59, 0x6c, 0xfa, 0x3b, 0xb5, 0xf8, 0x73, 0xda, 0xf4, 0xf7,\r
+  0x6a, 0xf1, 0x67, 0xd4, 0xe9, 0xef, 0xd6, 0x12, 0x3e, 0xf5, 0x1d, 0x27,\r
+  0xfc, 0xfd, 0x5a, 0x16, 0x9f, 0xfa, 0x6c, 0x98, 0xff, 0xaf, 0x9d, 0x70,\r
+  0xab, 0xef, 0x55, 0xe1, 0xff, 0x53, 0x68, 0xf8, 0x54, 0x5d, 0xbe, 0x5a,\r
+  0x94, 0xe9, 0x53, 0x7f, 0x43, 0xc3, 0xf3, 0x41, 0x3e, 0x55, 0x0e, 0xff,\r
+  0x5f, 0x43, 0x8b, 0x5b, 0xfd, 0xdd, 0xc0, 0x20, 0xda, 0x6a, 0xd7, 0x72,\r
+  0xfe, 0x7f, 0x88, 0xdc, 0x70, 0x6e, 0x2b, 0x7f, 0xef, 0xd7, 0xff, 0x05,\r
+  0xf3, 0x27, 0x9b, 0x95, 0x30, 0x4c, 0x00, 0x00\r
+};\r
 \r
 //==============================================================================\r
 #if JUCE_PUSH_NOTIFICATIONS && JUCE_MODULE_AVAILABLE_juce_gui_extra\r
@@ -208,6 +872,13 @@ DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowManagerLayoutParams28, "android/vie
  DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidWindowInsetsType, "android/view/WindowInsets$Type", 30)\r
 #undef JNI_CLASS_MEMBERS\r
 \r
+#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
+ FIELD (first,  "first",  "Ljava/lang/Object;") \\r
+ FIELD (second, "second", "Ljava/lang/Object;") \\r
+\r
+ DECLARE_JNI_CLASS (AndroidPair, "android/util/Pair")\r
+#undef JNI_CLASS_MEMBERS\r
+\r
 //==============================================================================\r
 namespace\r
 {\r
@@ -851,30 +1522,29 @@ public:
         }\r
     }\r
 \r
-    void handleKeyDownCallback (int k, int kc, int kbFlags)\r
+    static void handleKeyDownCallback (JNIEnv*, AndroidComponentPeer& t, int k, int kc, int kbFlags)\r
     {\r
         ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withOnlyMouseButtons()\r
                                                                        .withFlags (translateAndroidKeyboardFlags (kbFlags));\r
-        handleKeyPress (translateAndroidKeyCode (k), static_cast<juce_wchar> (kc));\r
+        t.handleKeyPress (translateAndroidKeyCode (k), static_cast<juce_wchar> (kc));\r
     }\r
 \r
-    void handleKeyUpCallback (int /*k*/, int /*kc*/)\r
+    static void handleKeyUpCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t, [[maybe_unused]] int k, [[maybe_unused]] int kc)\r
     {\r
     }\r
 \r
-    void handleBackButtonCallback()\r
+    static void handleBackButtonCallback (JNIEnv* env, AndroidComponentPeer& t)\r
     {\r
         bool handled = false;\r
 \r
         if (auto* app = JUCEApplicationBase::getInstance())\r
             handled = app->backButtonPressed();\r
 \r
-        if (isKioskModeComponent())\r
-            setNavBarsHidden (navBarsHidden);\r
+        if (t.isKioskModeComponent())\r
+            t.setNavBarsHidden (t.navBarsHidden);\r
 \r
         if (! handled)\r
         {\r
-            auto* env = getEnv();\r
             LocalRef<jobject> activity (getCurrentActivity());\r
 \r
             if (activity != nullptr)\r
@@ -885,17 +1555,27 @@ public:
         }\r
     }\r
 \r
-    void handleKeyboardHiddenCallback()\r
+    static void handleKeyboardHiddenCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t)\r
     {\r
         Component::unfocusAllComponents();\r
     }\r
 \r
-    void handleAppPausedCallback() {}\r
+    static void handleAppPausedCallback (JNIEnv*, [[maybe_unused]] AndroidComponentPeer& t) {}\r
+\r
+    static void handleAppResumedCallback (JNIEnv*, AndroidComponentPeer& t)\r
+    {\r
+        if (t.isKioskModeComponent())\r
+            t.setNavBarsHidden (t.navBarsHidden);\r
+    }\r
+\r
+    static jlong handleGetFocusedTextInputTargetCallback (JNIEnv*, AndroidComponentPeer& t)\r
+    {\r
+        return reinterpret_cast<jlong> (t.findCurrentTextInputTarget());\r
+    }\r
 \r
-    void handleAppResumedCallback()\r
+    static void handleMovedOrResizedCallback (JNIEnv*, AndroidComponentPeer& t)\r
     {\r
-        if (isKioskModeComponent())\r
-            setNavBarsHidden (navBarsHidden);\r
+        t.handleMovedOrResized();\r
     }\r
 \r
     //==============================================================================\r
@@ -911,9 +1591,9 @@ public:
         return nullptr;\r
     }\r
 \r
-    jboolean populateAccessibilityNodeInfoCallback (jint virtualViewId, jobject info) const\r
+    static jboolean populateAccessibilityNodeInfoCallback (JNIEnv*, const AndroidComponentPeer& t, jint virtualViewId, jobject info)\r
     {\r
-        if (auto* handle = getNativeHandleForViewId (virtualViewId))\r
+        if (auto* handle = t.getNativeHandleForViewId (virtualViewId))\r
         {\r
             handle->populateNodeInfo (info);\r
             return true;\r
@@ -922,53 +1602,53 @@ public:
         return false;\r
     }\r
 \r
-    jboolean handlePerformActionCallback (jint virtualViewId, jint action, jobject arguments) const\r
+    static jboolean handlePerformActionCallback (JNIEnv*, const AndroidComponentPeer& t, jint virtualViewId, jint action, jobject arguments)\r
     {\r
-        if (auto* handle = getNativeHandleForViewId (virtualViewId))\r
+        if (auto* handle = t.getNativeHandleForViewId (virtualViewId))\r
             return handle->performAction (action, arguments);\r
 \r
         return false;\r
     }\r
 \r
-    static jobject getFocusViewIdForHandler (const AccessibilityHandler* handler)\r
+    static jobject getFocusViewIdForHandler (JNIEnv* env, const AccessibilityHandler* handler)\r
     {\r
         if (handler != nullptr)\r
-            return getEnv()->NewObject (JavaInteger,\r
-                                        JavaInteger.constructor,\r
-                                        handler->getNativeImplementation()->getVirtualViewId());\r
+            return env->NewObject (JavaInteger,\r
+                                   JavaInteger.constructor,\r
+                                   handler->getNativeImplementation()->getVirtualViewId());\r
 \r
         return nullptr;\r
     }\r
 \r
-    jobject getInputFocusViewIdCallback()\r
+    static jobject getInputFocusViewIdCallback (JNIEnv* env, AndroidComponentPeer& t)\r
     {\r
-        if (auto* comp = dynamic_cast<Component*> (findCurrentTextInputTarget()))\r
-            return getFocusViewIdForHandler (comp->getAccessibilityHandler());\r
+        if (auto* comp = dynamic_cast<Component*> (t.findCurrentTextInputTarget()))\r
+            return getFocusViewIdForHandler (env, comp->getAccessibilityHandler());\r
 \r
         return nullptr;\r
     }\r
 \r
-    jobject getAccessibilityFocusViewIdCallback() const\r
+    static jobject getAccessibilityFocusViewIdCallback (JNIEnv* env, const AndroidComponentPeer& t)\r
     {\r
-        if (auto* handler = component.getAccessibilityHandler())\r
+        if (auto* handler = t.component.getAccessibilityHandler())\r
         {\r
             if (auto* modal = Component::getCurrentlyModalComponent())\r
             {\r
-                if (! component.isParentOf (modal)\r
-                     && component.isCurrentlyBlockedByAnotherModalComponent())\r
+                if (! t.component.isParentOf (modal)\r
+                     && t.component.isCurrentlyBlockedByAnotherModalComponent())\r
                 {\r
                     if (auto* modalHandler = modal->getAccessibilityHandler())\r
                     {\r
                         if (auto* focusChild = modalHandler->getChildFocus())\r
-                            return getFocusViewIdForHandler (focusChild);\r
+                            return getFocusViewIdForHandler (env, focusChild);\r
 \r
-                        return getFocusViewIdForHandler (modalHandler);\r
+                        return getFocusViewIdForHandler (env, modalHandler);\r
                     }\r
                 }\r
             }\r
 \r
             if (auto* focusChild = handler->getChildFocus())\r
-                return getFocusViewIdForHandler (focusChild);\r
+                return getFocusViewIdForHandler (env, focusChild);\r
         }\r
 \r
         return nullptr;\r
@@ -989,54 +1669,49 @@ public:
             view.callBooleanMethod (AndroidView.requestFocus);\r
     }\r
 \r
-    void handleFocusChangeCallback (bool hasFocus)\r
+    static void handleFocusChangeCallback (JNIEnv*, AndroidComponentPeer& t, bool hasFocus)\r
     {\r
-        if (isFullScreen())\r
-            setFullScreen (true);\r
+        if (t.isFullScreen())\r
+            t.setFullScreen (true);\r
 \r
         if (hasFocus)\r
-            handleFocusGain();\r
+            t.handleFocusGain();\r
         else\r
-            handleFocusLoss();\r
+            t.handleFocusLoss();\r
     }\r
 \r
-    static const char* getVirtualKeyboardType (TextInputTarget::VirtualKeyboardType type) noexcept\r
+    void textInputRequired (Point<int>, TextInputTarget& target) override\r
     {\r
-        switch (type)\r
-        {\r
-            case TextInputTarget::textKeyboard:          return "text";\r
-            case TextInputTarget::numericKeyboard:       return "number";\r
-            case TextInputTarget::decimalKeyboard:       return "numberDecimal";\r
-            case TextInputTarget::urlKeyboard:           return "textUri";\r
-            case TextInputTarget::emailAddressKeyboard:  return "textEmailAddress";\r
-            case TextInputTarget::phoneNumberKeyboard:   return "phone";\r
-            default:                                     jassertfalse; break;\r
-        }\r
-\r
-        return "text";\r
+        const auto region = target.getHighlightedRegion();\r
+        view.callVoidMethod (ComponentPeerView.showKeyboard,\r
+                             static_cast<jint> (target.getKeyboardType()),\r
+                             static_cast<jint> (region.getStart()),\r
+                             static_cast<jint> (region.getEnd()));\r
     }\r
 \r
-    void textInputRequired (Point<int>, TextInputTarget& target) override\r
+    void closeInputMethodContext() override\r
     {\r
-        view.callVoidMethod (ComponentPeerView.showKeyboard,\r
-                             javaString (getVirtualKeyboardType (target.getKeyboardType())).get());\r
+        getEnv()->CallVoidMethod (view, ComponentPeerView.closeInputMethodContext);\r
     }\r
 \r
     void dismissPendingTextInput() override\r
     {\r
         closeInputMethodContext();\r
 \r
-        view.callVoidMethod (ComponentPeerView.showKeyboard, javaString ("").get());\r
+        view.callVoidMethod (ComponentPeerView.hideKeyboard);\r
 \r
         if (! isTimerRunning())\r
             startTimer (500);\r
     }\r
 \r
     //==============================================================================\r
-    void handlePaintCallback (jobject canvas, jobject paint)\r
+    static void handleDoFrameCallback (JNIEnv*, AndroidComponentPeer& t, [[maybe_unused]] int64 frameTimeNanos)\r
     {\r
-        auto* env = getEnv();\r
+        t.vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
+    }\r
 \r
+    static void handlePaintCallback (JNIEnv* env, AndroidComponentPeer& t, jobject canvas, jobject paint)\r
+    {\r
         jobject rect = env->CallObjectMethod (canvas, AndroidCanvas.getClipBounds);\r
         auto left   = env->GetIntField (rect, AndroidRect.left);\r
         auto top    = env->GetIntField (rect, AndroidRect.top);\r
@@ -1051,30 +1726,30 @@ public:
 \r
         auto sizeNeeded = clip.getWidth() * clip.getHeight();\r
 \r
-        if (sizeAllocated < sizeNeeded)\r
+        if (t.sizeAllocated < sizeNeeded)\r
         {\r
-            buffer.clear();\r
-            sizeAllocated = sizeNeeded;\r
-            buffer = GlobalRef (LocalRef<jobject> ((jobject) env->NewIntArray (sizeNeeded)));\r
+            t.buffer.clear();\r
+            t.sizeAllocated = sizeNeeded;\r
+            t.buffer = GlobalRef (LocalRef<jobject> ((jobject) env->NewIntArray (sizeNeeded)));\r
         }\r
 \r
-        if (jint* dest = env->GetIntArrayElements ((jintArray) buffer.get(), nullptr))\r
+        if (jint* dest = env->GetIntArrayElements ((jintArray) t.buffer.get(), nullptr))\r
         {\r
             {\r
                 Image temp (new PreallocatedImage (clip.getWidth(), clip.getHeight(),\r
-                                                   dest, ! component.isOpaque()));\r
+                                                   dest, ! t.component.isOpaque()));\r
 \r
                 {\r
                     LowLevelGraphicsSoftwareRenderer g (temp);\r
                     g.setOrigin (-clip.getPosition());\r
-                    g.addTransform (AffineTransform::scale (scale));\r
-                    handlePaint (g);\r
+                    g.addTransform (AffineTransform::scale (t.scale));\r
+                    t.handlePaint (g);\r
                 }\r
             }\r
 \r
-            env->ReleaseIntArrayElements ((jintArray) buffer.get(), dest, 0);\r
+            env->ReleaseIntArrayElements ((jintArray) t.buffer.get(), dest, 0);\r
 \r
-            env->CallVoidMethod (canvas, AndroidCanvas.drawBitmap, (jintArray) buffer.get(), 0, clip.getWidth(),\r
+            env->CallVoidMethod (canvas, AndroidCanvas.drawBitmap, (jintArray) t.buffer.get(), 0, clip.getWidth(),\r
                                  (jfloat) clip.getX(), (jfloat) clip.getY(),\r
                                  clip.getWidth(), clip.getHeight(), true, paint);\r
         }\r
@@ -1134,81 +1809,140 @@ public:
     };\r
 \r
 private:\r
+    template <auto Member>\r
+    static void mouseCallbackWrapper (JNIEnv*, AndroidComponentPeer& t, jint i, jfloat x, jfloat y, jlong time) { return (t.*Member) (i, Point<float> { x, y }, time); }\r
+\r
     //==============================================================================\r
-    #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
-     METHOD   (create,                           "<init>",                        "(Landroid/content/Context;ZJ)V") \\r
-     METHOD   (clear,                            "clear",                         "()V") \\r
-     METHOD   (setViewName,                      "setViewName",                   "(Ljava/lang/String;)V") \\r
-     METHOD   (setVisible,                       "setVisible",                    "(Z)V") \\r
-     METHOD   (isVisible,                        "isVisible",                     "()Z") \\r
-     METHOD   (containsPoint,                    "containsPoint",                 "(II)Z") \\r
-     METHOD   (showKeyboard,                     "showKeyboard",                  "(Ljava/lang/String;)V") \\r
-     METHOD   (setSystemUiVisibilityCompat,      "setSystemUiVisibilityCompat",   "(I)V") \\r
-     CALLBACK (handlePaintJni,                   "handlePaint",                   "(JLandroid/graphics/Canvas;Landroid/graphics/Paint;)V") \\r
-     CALLBACK (handleMouseDownJni,               "handleMouseDown",               "(JIFFJ)V") \\r
-     CALLBACK (handleMouseDragJni,               "handleMouseDrag",               "(JIFFJ)V") \\r
-     CALLBACK (handleMouseUpJni,                 "handleMouseUp",                 "(JIFFJ)V") \\r
-     CALLBACK (handleAccessibleHoverJni,         "handleAccessibilityHover",      "(JIFFJ)V") \\r
-     CALLBACK (handleKeyDownJni,                 "handleKeyDown",                 "(JIII)V") \\r
-     CALLBACK (handleKeyUpJni,                   "handleKeyUp",                   "(JII)V") \\r
-     CALLBACK (handleBackButtonJni,              "handleBackButton",              "(J)V") \\r
-     CALLBACK (handleKeyboardHiddenJni,          "handleKeyboardHidden",          "(J)V") \\r
-     CALLBACK (viewSizeChangedJni,               "viewSizeChanged",               "(J)V") \\r
-     CALLBACK (focusChangedJni,                  "focusChanged",                  "(JZ)V") \\r
-     CALLBACK (handleAppPausedJni,               "handleAppPaused",               "(J)V") \\r
-     CALLBACK (handleAppResumedJni,              "handleAppResumed",              "(J)V") \\r
-     CALLBACK (populateAccessibilityNodeInfoJni, "populateAccessibilityNodeInfo", "(JILandroid/view/accessibility/AccessibilityNodeInfo;)Z") \\r
-     CALLBACK (handlePerformActionJni,           "handlePerformAction",           "(JIILandroid/os/Bundle;)Z") \\r
-     CALLBACK (getInputFocusViewIdJni,           "getInputFocusViewId",           "(J)Ljava/lang/Integer;") \\r
-     CALLBACK (getAccessibilityFocusViewIdJni,   "getAccessibilityFocusViewId",   "(J)Ljava/lang/Integer;") \\r
-\r
-    DECLARE_JNI_CLASS_WITH_BYTECODE (ComponentPeerView, "com/rmsl/juce/ComponentPeerView", 16, javaComponentPeerView, sizeof (javaComponentPeerView))\r
-    #undef JNI_CLASS_MEMBERS\r
-\r
-    static void JNICALL handlePaintJni          (JNIEnv*, jobject /*view*/, jlong host, jobject canvas, jobject paint)           { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handlePaintCallback (canvas, paint); }\r
-    static void JNICALL handleMouseDownJni      (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time)  { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMouseDownCallback (i, Point<float> ((float) x, (float) y), (int64) time); }\r
-    static void JNICALL handleMouseDragJni      (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time)  { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMouseDragCallback (i, Point<float> ((float) x, (float) y), (int64) time); }\r
-    static void JNICALL handleMouseUpJni        (JNIEnv*, jobject /*view*/, jlong host, jint i, jfloat x, jfloat y, jlong time)  { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMouseUpCallback   (i, Point<float> ((float) x, (float) y), (int64) time); }\r
-    static void JNICALL handleAccessibleHoverJni(JNIEnv*, jobject /*view*/, jlong host, jint c, jfloat x, jfloat y, jlong time)  { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleAccessibilityHoverCallback ((int) c, Point<float> ((float) x, (float) y), (int64) time); }\r
-    static void JNICALL viewSizeChangedJni      (JNIEnv*, jobject /*view*/, jlong host)                                          { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleMovedOrResized(); }\r
-    static void JNICALL focusChangedJni         (JNIEnv*, jobject /*view*/, jlong host, jboolean hasFocus)                       { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleFocusChangeCallback (hasFocus); }\r
-    static void JNICALL handleKeyDownJni        (JNIEnv*, jobject /*view*/, jlong host, jint k, jint kc, jint kbFlags)           { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleKeyDownCallback ((int) k, (int) kc, (int) kbFlags); }\r
-    static void JNICALL handleKeyUpJni          (JNIEnv*, jobject /*view*/, jlong host, jint k, jint kc)                         { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleKeyUpCallback ((int) k, (int) kc); }\r
-    static void JNICALL handleBackButtonJni     (JNIEnv*, jobject /*view*/, jlong host)                                          { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleBackButtonCallback(); }\r
-    static void JNICALL handleKeyboardHiddenJni (JNIEnv*, jobject /*view*/, jlong host)                                          { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleKeyboardHiddenCallback(); }\r
-    static void JNICALL handleAppPausedJni      (JNIEnv*, jobject /*view*/, jlong host)                                          { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleAppPausedCallback(); }\r
-    static void JNICALL handleAppResumedJni     (JNIEnv*, jobject /*view*/, jlong host)                                          { if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host)) myself->handleAppResumedCallback(); }\r
-\r
-    static jboolean JNICALL populateAccessibilityNodeInfoJni (JNIEnv*, jobject /*view*/, jlong host, jint virtualViewId, jobject info)\r
-    {\r
-        if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host))\r
-            return myself->populateAccessibilityNodeInfoCallback (virtualViewId, info);\r
+   #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
+    METHOD   (create,                           "<init>",                        "(Landroid/content/Context;ZJ)V") \\r
+    METHOD   (clear,                            "clear",                         "()V") \\r
+    METHOD   (setViewName,                      "setViewName",                   "(Ljava/lang/String;)V") \\r
+    METHOD   (setVisible,                       "setVisible",                    "(Z)V") \\r
+    METHOD   (isVisible,                        "isVisible",                     "()Z") \\r
+    METHOD   (containsPoint,                    "containsPoint",                 "(II)Z") \\r
+    METHOD   (showKeyboard,                     "showKeyboard",                  "(III)V") \\r
+    METHOD   (hideKeyboard,                     "hideKeyboard",                  "()V") \\r
+    METHOD   (closeInputMethodContext,          "closeInputMethodContext",       "()V") \\r
+    METHOD   (setSystemUiVisibilityCompat,      "setSystemUiVisibilityCompat",   "(I)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleDoFrameCallback>,                    "handleDoFrame",                                    "(JJ)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handlePaintCallback>,                      "handlePaint",                                      "(JLandroid/graphics/Canvas;Landroid/graphics/Paint;)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyDownCallback>,                    "handleKeyDown",                                    "(JIII)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyUpCallback>,                      "handleKeyUp",                                      "(JII)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleBackButtonCallback>,                 "handleBackButton",                                 "(J)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleKeyboardHiddenCallback>,             "handleKeyboardHidden",                             "(J)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleGetFocusedTextInputTargetCallback>,  "getFocusedTextInputTargetPointer",                 "(J)J") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleMovedOrResizedCallback>,             "viewSizeChanged",                                  "(J)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleFocusChangeCallback>,                "focusChanged",                                     "(JZ)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleAppPausedCallback>,                  "handleAppPaused",                                  "(J)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handleAppResumedCallback>,                 "handleAppResumed",                                 "(J)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::populateAccessibilityNodeInfoCallback>,    "populateAccessibilityNodeInfo",                    "(JILandroid/view/accessibility/AccessibilityNodeInfo;)Z") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::handlePerformActionCallback>,              "handlePerformAction",                              "(JIILandroid/os/Bundle;)Z") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::getInputFocusViewIdCallback>,              "getInputFocusViewId",                              "(J)Ljava/lang/Integer;") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::getAccessibilityFocusViewIdCallback>,      "getAccessibilityFocusViewId",                      "(J)Ljava/lang/Integer;") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetIsTextInputActive>,         "textInputTargetIsTextInputActive",                 "(J)Z") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetHighlightedRegionBegin>, "textInputTargetGetHighlightedRegionBegin",         "(J)I") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetHighlightedRegionEnd>,   "textInputTargetGetHighlightedRegionEnd",           "(J)I") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetSetHighlightedRegion>,      "textInputTargetSetHighlightedRegion",              "(JII)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetTextInRange>,            "textInputTargetGetTextInRange",                    "(JII)Ljava/lang/String;") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetInsertTextAtCaret>,         "textInputTargetInsertTextAtCaret",                 "(JLjava/lang/String;)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetCaretPosition>,          "textInputTargetGetCaretPosition",                  "(J)I") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetTotalNumChars>,          "textInputTargetGetTotalNumChars",                  "(J)I") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetCharIndexForPoint>,      "textInputTargetGetCharIndexForPoint",              "(JLandroid/graphics/Point;)I") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetGetKeyboardType>,           "textInputTargetGetKeyboardType",                   "(J)I") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::textInputTargetSetTemporaryUnderlining>,   "textInputTargetSetTemporaryUnderlining",           "(JLjava/util/List;)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseDownCallback>>,          "handleMouseDown",               "(JIFFJ)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseDragCallback>>,          "handleMouseDrag",               "(JIFFJ)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleMouseUpCallback>>,            "handleMouseUp",                 "(JIFFJ)V") \\r
+    CALLBACK (generatedCallback<&AndroidComponentPeer::mouseCallbackWrapper<&AndroidComponentPeer::handleAccessibilityHoverCallback>>, "handleAccessibilityHover",      "(JIFFJ)V") \\r
 \r
-        return false;\r
+    DECLARE_JNI_CLASS_WITH_BYTECODE (ComponentPeerView, "com/rmsl/juce/ComponentPeerView", 16, javaComponentPeerView)\r
+   #undef JNI_CLASS_MEMBERS\r
+\r
+    static jboolean textInputTargetIsTextInputActive (JNIEnv*, const TextInputTarget& t)\r
+    {\r
+        return t.isTextInputActive();\r
     }\r
 \r
-    static jboolean JNICALL handlePerformActionJni (JNIEnv*, jobject /*view*/, jlong host, jint virtualViewId, jint action, jobject arguments)\r
+    static jint textInputTargetGetHighlightedRegionBegin (JNIEnv*, const TextInputTarget& t)\r
     {\r
-        if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host))\r
-            return myself->handlePerformActionCallback (virtualViewId, action, arguments);\r
+        return t.getHighlightedRegion().getStart();\r
+    }\r
 \r
-        return false;\r
+    static jint textInputTargetGetHighlightedRegionEnd (JNIEnv*, const TextInputTarget& t)\r
+    {\r
+        return t.getHighlightedRegion().getEnd();\r
+    }\r
+\r
+    static void textInputTargetSetHighlightedRegion (JNIEnv*, TextInputTarget& t, jint b, jint e)\r
+    {\r
+        t.setHighlightedRegion ({ b, e });\r
     }\r
 \r
-    static jobject JNICALL getInputFocusViewIdJni (JNIEnv*, jobject /*view*/, jlong host)\r
+    static jstring textInputTargetGetTextInRange (JNIEnv* env, const TextInputTarget& t, jint b, jint e)\r
     {\r
-        if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host))\r
-            return myself->getInputFocusViewIdCallback();\r
+        return env->NewStringUTF (t.getTextInRange ({ b, e }).toUTF8());\r
+    }\r
 \r
-        return nullptr;\r
+    static void textInputTargetInsertTextAtCaret (JNIEnv*, TextInputTarget& t, jstring text)\r
+    {\r
+        t.insertTextAtCaret (juceString (text));\r
     }\r
 \r
-    static jobject JNICALL getAccessibilityFocusViewIdJni (JNIEnv*, jobject /*view*/, jlong host)\r
+    static jint textInputTargetGetCaretPosition (JNIEnv*, const TextInputTarget& t)\r
     {\r
-        if (auto* myself = reinterpret_cast<AndroidComponentPeer*> (host))\r
-            return myself->getAccessibilityFocusViewIdCallback();\r
+        return t.getCaretPosition();\r
+    }\r
 \r
-        return nullptr;\r
+    static jint textInputTargetGetTotalNumChars (JNIEnv*, const TextInputTarget& t)\r
+    {\r
+        return t.getTotalNumChars();\r
+    }\r
+\r
+    static jint textInputTargetGetCharIndexForPoint (JNIEnv* env, const TextInputTarget& t, jobject point)\r
+    {\r
+        return t.getCharIndexForPoint ({ env->GetIntField (point, AndroidPoint.x),\r
+                                         env->GetIntField (point, AndroidPoint.y) });\r
+    }\r
+\r
+    static jint textInputTargetGetKeyboardType (JNIEnv*, TextInputTarget& t)\r
+    {\r
+        return t.getKeyboardType();\r
+    }\r
+\r
+    static std::optional<Range<int>> getRangeFromPair (JNIEnv* env, jobject pair)\r
+    {\r
+        if (pair == nullptr)\r
+            return {};\r
+\r
+        const auto first  = env->GetObjectField (pair, AndroidPair.first);\r
+        const auto second = env->GetObjectField (pair, AndroidPair.second);\r
+\r
+        if (first == nullptr || second == nullptr)\r
+            return {};\r
+\r
+        const auto begin = env->CallIntMethod (first,  JavaInteger.intValue);\r
+        const auto end   = env->CallIntMethod (second, JavaInteger.intValue);\r
+\r
+        return Range<int> { begin, end };\r
+    }\r
+\r
+    static Array<Range<int>> javaListOfPairToArrayOfRange (JNIEnv* env, jobject list)\r
+    {\r
+        if (list == nullptr)\r
+            return {};\r
+\r
+        Array<Range<int>> result;\r
+\r
+        for (jint i = 0; i < env->CallIntMethod (list, JavaList.size); ++i)\r
+            if (const auto range = getRangeFromPair (env, env->CallObjectMethod (list, JavaList.get, i)))\r
+                result.add (*range);\r
+\r
+        return result;\r
+    }\r
+\r
+    static void textInputTargetSetTemporaryUnderlining (JNIEnv* env, TextInputTarget& t, jobject list)\r
+    {\r
+        t.setTemporaryUnderlining (javaListOfPairToArrayOfRange (env, list));\r
     }\r
 \r
     //==============================================================================\r
@@ -1378,7 +2112,6 @@ Point<float> AndroidComponentPeer::lastMousePos;
 int64 AndroidComponentPeer::touchesDown = 0;\r
 AndroidComponentPeer* AndroidComponentPeer::frontWindow = nullptr;\r
 GlobalRef AndroidComponentPeer::activityCallbackListener;\r
-AndroidComponentPeer::ComponentPeerView_Class AndroidComponentPeer::ComponentPeerView;\r
 \r
 //==============================================================================\r
 ComponentPeer* Component::createNewPeer (int styleFlags, void* nativeWindow)\r
@@ -1787,10 +2520,8 @@ bool Desktop::isScreenSaverEnabled()
 }\r
 \r
 //==============================================================================\r
-void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, bool allowMenusAndBars)\r
+void Desktop::setKioskComponent (Component* kioskComp, bool enableOrDisable, [[maybe_unused]] bool allowMenusAndBars)\r
 {\r
-    ignoreUnused (allowMenusAndBars);\r
-\r
     if (AndroidComponentPeer* peer = dynamic_cast<AndroidComponentPeer*> (kioskComp->getPeer()))\r
         peer->setFullScreen (enableOrDisable);\r
     else\r
@@ -1918,7 +2649,7 @@ void Displays::findDisplays (float masterScale)
 {\r
     auto* env = getEnv();\r
 \r
-    LocalRef<jobject> usableSize (env->NewObject (AndroidPoint, AndroidPoint.create, 0, 0));\r
+    LocalRef<jobject> usableSize (makeAndroidPoint ({}));\r
     LocalRef<jstring> windowServiceString (javaString ("window"));\r
     LocalRef<jobject> displayMetrics (env->NewObject (AndroidDisplayMetrics, AndroidDisplayMetrics.create));\r
     LocalRef<jobject> windowManager (env->CallObjectMethod (getAppContext().get(), AndroidContext.getSystemService, windowServiceString.get()));\r
@@ -2169,8 +2900,6 @@ const int KeyPress::rewindKey               = extendedKeyModifier + 72;
          juce_handleOnResume();\r
      }\r
  };\r
-\r
- JuceActivityNewIntentListener::JavaActivity_Class JuceActivityNewIntentListener::JavaActivity;\r
 #endif\r
 \r
 } // namespace juce\r
index 8aea94480450efa6beb68d9f8b222f58ed694fdd..04203b55b880be81e975bc08c8a69e236b2d4e9b 100644 (file)
@@ -104,12 +104,9 @@ private:
 \r
         controller.get().excludedActivityTypes = nil;\r
 \r
-        controller.get().completionWithItemsHandler = ^ (UIActivityType type, BOOL completed,\r
-                                                         NSArray* returnedItems, NSError* error)\r
+        controller.get().completionWithItemsHandler = ^([[maybe_unused]] UIActivityType type, BOOL completed,\r
+                                                        [[maybe_unused]] NSArray* returnedItems, NSError* error)\r
         {\r
-            ignoreUnused (type);\r
-            ignoreUnused (returnedItems);\r
-\r
             succeeded = completed;\r
 \r
             if (error != nil)\r
index 5da0b68eac56545e06501597e24aaa72ba720845..47b5690eddbf9e3727ee985c0bc511282bb1393f 100644 (file)
   ==============================================================================\r
 */\r
 \r
+@interface FileChooserControllerClass : UIDocumentPickerViewController\r
+- (void) setParent: (FileChooser::Native*) ptr;\r
+@end\r
+\r
+@interface FileChooserDelegateClass : NSObject<UIDocumentPickerDelegate>\r
+- (id) initWithOwner: (FileChooser::Native*) owner;\r
+@end\r
+\r
 namespace juce\r
 {\r
 \r
@@ -33,18 +41,158 @@ namespace juce
 \r
 class FileChooser::Native  : public FileChooser::Pimpl,\r
                              public Component,\r
-                             private AsyncUpdater\r
+                             public AsyncUpdater,\r
+                             public std::enable_shared_from_this<Native>\r
 {\r
 public:\r
+    static std::shared_ptr<Native> make (FileChooser& fileChooser, int flags)\r
+    {\r
+        std::shared_ptr<Native> result { new Native (fileChooser, flags) };\r
+        /*  Must be called after forming a shared_ptr to an instance of this class.\r
+            Note that we can't call this directly inside the class constructor, because\r
+            the owning shared_ptr might not yet exist.\r
+        */\r
+        [result->controller.get() setParent: result.get()];\r
+        return result;\r
+    }\r
+\r
+    ~Native() override\r
+    {\r
+        exitModalState (0);\r
+    }\r
+\r
+    void launch() override\r
+    {\r
+        jassert (shared_from_this() != nullptr);\r
+\r
+        /*  Normally, when deleteWhenDismissed is true, the modal component manger will keep a copy of a raw pointer\r
+            to our component and delete it when the modal state has ended. However, this is incompatible with\r
+            our class being tracked by shared_ptr as it will force delete our class regardless of the current\r
+            reference count. On the other hand, it's important that the modal manager keeps a reference as it can\r
+            sometimes be the only reference to our class.\r
+\r
+            To do this, we set deleteWhenDismissed to false so that the modal component manager does not delete\r
+            our class. Instead, we pass in a lambda which captures a shared_ptr to ourselves to increase the\r
+            reference count while the component is modal.\r
+        */\r
+        enterModalState (true,\r
+                         ModalCallbackFunction::create ([_self = shared_from_this()] (int) {}),\r
+                         false);\r
+    }\r
+\r
+    void runModally() override\r
+    {\r
+       #if JUCE_MODAL_LOOPS_PERMITTED\r
+        launch();\r
+        runModalLoop();\r
+       #else\r
+        jassertfalse;\r
+       #endif\r
+    }\r
+\r
+    void parentHierarchyChanged() override\r
+    {\r
+        auto* newPeer = dynamic_cast<UIViewComponentPeer*> (getPeer());\r
+\r
+        if (peer != newPeer)\r
+        {\r
+            peer = newPeer;\r
+\r
+            if (peer != nullptr)\r
+            {\r
+                if (auto* parentController = peer->controller)\r
+                    [parentController showViewController: controller.get() sender: parentController];\r
+\r
+                peer->toFront (false);\r
+            }\r
+        }\r
+    }\r
+\r
+    void handleAsyncUpdate() override\r
+    {\r
+        pickerWasCancelled();\r
+    }\r
+\r
+    //==============================================================================\r
+    void didPickDocumentsAtURLs (NSArray<NSURL*>* urls)\r
+    {\r
+        cancelPendingUpdate();\r
+\r
+        const auto isWriting =  controller.get().documentPickerMode == UIDocumentPickerModeExportToService\r
+                             || controller.get().documentPickerMode == UIDocumentPickerModeMoveToService;\r
+        const auto accessOptions = isWriting ? 0 : NSFileCoordinatorReadingWithoutChanges;\r
+\r
+        auto* fileCoordinator = [[[NSFileCoordinator alloc] initWithFilePresenter: nil] autorelease];\r
+        auto* intents = [[[NSMutableArray alloc] init] autorelease];\r
+\r
+        for (NSURL* url in urls)\r
+        {\r
+            auto* fileAccessIntent = isWriting\r
+                                   ? [NSFileAccessIntent writingIntentWithURL: url options: accessOptions]\r
+                                   : [NSFileAccessIntent readingIntentWithURL: url options: accessOptions];\r
+            [intents addObject: fileAccessIntent];\r
+        }\r
+\r
+        [fileCoordinator coordinateAccessWithIntents: intents queue: [NSOperationQueue mainQueue] byAccessor: ^(NSError* err)\r
+        {\r
+            if (err != nil)\r
+            {\r
+                [[maybe_unused]] auto desc = [err localizedDescription];\r
+                jassertfalse;\r
+                return;\r
+            }\r
+\r
+            Array<URL> result;\r
+\r
+            for (NSURL* url in urls)\r
+            {\r
+                [url startAccessingSecurityScopedResource];\r
+\r
+                NSError* error = nil;\r
+\r
+                auto* bookmark = [url bookmarkDataWithOptions: 0\r
+                               includingResourceValuesForKeys: nil\r
+                                                relativeToURL: nil\r
+                                                        error: &error];\r
+\r
+                [bookmark retain];\r
+\r
+                [url stopAccessingSecurityScopedResource];\r
+\r
+                URL juceUrl (nsStringToJuce ([url absoluteString]));\r
+\r
+                if (error == nil)\r
+                {\r
+                    setURLBookmark (juceUrl, (void*) bookmark);\r
+                }\r
+                else\r
+                {\r
+                    [[maybe_unused]] auto desc = [error localizedDescription];\r
+                    jassertfalse;\r
+                }\r
+\r
+                result.add (std::move (juceUrl));\r
+            }\r
+\r
+            passResultsToInitiator (std::move (result));\r
+        }];\r
+    }\r
+\r
+    void didPickDocumentAtURL (NSURL* url)\r
+    {\r
+        didPickDocumentsAtURLs (@[url]);\r
+    }\r
+\r
+    void pickerWasCancelled()\r
+    {\r
+        passResultsToInitiator ({});\r
+    }\r
+\r
+private:\r
     Native (FileChooser& fileChooser, int flags)\r
         : owner (fileChooser)\r
     {\r
-        static FileChooserDelegateClass delegateClass;\r
-        delegate.reset ([delegateClass.createInstance() init]);\r
-        FileChooserDelegateClass::setOwner (delegate.get(), this);\r
-\r
-        static FileChooserControllerClass controllerClass;\r
-        auto* controllerClassInstance = controllerClass.createInstance();\r
+        delegate.reset ([[FileChooserDelegateClass alloc] initWithOwner: this]);\r
 \r
         String firstFileExtension;\r
         auto utTypeArray = createNSArrayFromStringArray (getUTTypesForWildcards (owner.filters, firstFileExtension));\r
@@ -78,20 +226,17 @@ public:
 \r
             auto url = [[NSURL alloc] initFileURLWithPath: juceStringToNS (currentFileOrDirectory.getFullPathName())];\r
 \r
-            controller.reset ([controllerClassInstance initWithURL: url\r
-                                                            inMode: pickerMode]);\r
-\r
+            controller.reset ([[FileChooserControllerClass alloc] initWithURL: url inMode: pickerMode]);\r
             [url release];\r
         }\r
         else\r
         {\r
-            controller.reset ([controllerClassInstance initWithDocumentTypes: utTypeArray\r
-                                                                      inMode: UIDocumentPickerModeOpen]);\r
+            controller.reset ([[FileChooserControllerClass alloc] initWithDocumentTypes: utTypeArray inMode: UIDocumentPickerModeOpen]);\r
+\r
             if (@available (iOS 11.0, *))\r
                 [controller.get() setAllowsMultipleSelection: (flags & FileBrowserComponent::canSelectMultipleItems) != 0];\r
         }\r
 \r
-        FileChooserControllerClass::setOwner (controller.get(), this);\r
 \r
         [controller.get() setDelegate: delegate.get()];\r
         [controller.get() setModalTransitionStyle: UIModalTransitionStyleCrossDissolve];\r
@@ -128,58 +273,24 @@ public:
         }\r
     }\r
 \r
-    ~Native() override\r
+    void passResultsToInitiator (Array<URL> urls)\r
     {\r
+        cancelPendingUpdate();\r
         exitModalState (0);\r
 \r
-        // Our old peer may not have received a becomeFirstResponder call at this point,\r
-        // so the static currentlyFocusedPeer may be null.\r
-        // We'll try to find an appropriate peer to focus.\r
-\r
+        // If the caller attempts to show a platform-native dialog box inside the results callback (e.g. in the DialogsDemo)\r
+        // then the original peer must already have focus. Otherwise, there's a danger that either the invisible FileChooser\r
+        // components will display the popup, locking the application, or maybe no component will have focus, and the\r
+        // dialog won't show at all.\r
         for (auto i = 0; i < ComponentPeer::getNumPeers(); ++i)\r
             if (auto* p = ComponentPeer::getPeer (i))\r
                 if (p != getPeer())\r
                     if (auto* view = (UIView*) p->getNativeHandle())\r
-                        [view becomeFirstResponder];\r
-    }\r
-\r
-    void launch() override\r
-    {\r
-        enterModalState (true, nullptr, true);\r
-    }\r
-\r
-    void runModally() override\r
-    {\r
-       #if JUCE_MODAL_LOOPS_PERMITTED\r
-        runModalLoop();\r
-       #else\r
-        jassertfalse;\r
-       #endif\r
-    }\r
-\r
-    void parentHierarchyChanged() override\r
-    {\r
-        auto* newPeer = dynamic_cast<UIViewComponentPeer*> (getPeer());\r
-\r
-        if (peer != newPeer)\r
-        {\r
-            peer = newPeer;\r
-\r
-            if (peer != nullptr)\r
-            {\r
-                if (auto* parentController = peer->controller)\r
-                    [parentController showViewController: controller.get() sender: parentController];\r
+                        if ([view becomeFirstResponder] && [view isFirstResponder])\r
+                            break;\r
 \r
-                peer->toFront (false);\r
-            }\r
-        }\r
-    }\r
-\r
-private:\r
-    //==============================================================================\r
-    void handleAsyncUpdate() override\r
-    {\r
-        pickerWasCancelled();\r
+        // Calling owner.finished will delete this Pimpl instance, so don't call any more member functions here!\r
+        owner.finished (std::move (urls));\r
     }\r
 \r
     //==============================================================================\r
@@ -235,156 +346,12 @@ private:
         return filename;\r
     }\r
 \r
-    //==============================================================================\r
-    void didPickDocumentsAtURLs (NSArray<NSURL*>* urls)\r
-    {\r
-        cancelPendingUpdate();\r
-\r
-        const auto isWriting =  controller.get().documentPickerMode == UIDocumentPickerModeExportToService\r
-                             || controller.get().documentPickerMode == UIDocumentPickerModeMoveToService;\r
-        const auto accessOptions = isWriting ? 0 : NSFileCoordinatorReadingWithoutChanges;\r
-\r
-        auto* fileCoordinator = [[[NSFileCoordinator alloc] initWithFilePresenter: nil] autorelease];\r
-        auto* intents = [[[NSMutableArray alloc] init] autorelease];\r
-\r
-        for (NSURL* url in urls)\r
-        {\r
-            auto* fileAccessIntent = isWriting\r
-                                   ? [NSFileAccessIntent writingIntentWithURL: url options: accessOptions]\r
-                                   : [NSFileAccessIntent readingIntentWithURL: url options: accessOptions];\r
-            [intents addObject: fileAccessIntent];\r
-        }\r
-\r
-        [fileCoordinator coordinateAccessWithIntents: intents queue: [NSOperationQueue mainQueue] byAccessor: ^(NSError* err)\r
-        {\r
-            if (err != nil)\r
-            {\r
-                auto desc = [err localizedDescription];\r
-                ignoreUnused (desc);\r
-                jassertfalse;\r
-                return;\r
-            }\r
-\r
-            Array<URL> result;\r
-\r
-            for (NSURL* url in urls)\r
-            {\r
-                [url startAccessingSecurityScopedResource];\r
-\r
-                NSError* error = nil;\r
-\r
-                auto* bookmark = [url bookmarkDataWithOptions: 0\r
-                               includingResourceValuesForKeys: nil\r
-                                                relativeToURL: nil\r
-                                                        error: &error];\r
-\r
-                [bookmark retain];\r
-\r
-                [url stopAccessingSecurityScopedResource];\r
-\r
-                URL juceUrl (nsStringToJuce ([url absoluteString]));\r
-\r
-                if (error == nil)\r
-                {\r
-                    setURLBookmark (juceUrl, (void*) bookmark);\r
-                }\r
-                else\r
-                {\r
-                    auto desc = [error localizedDescription];\r
-                    ignoreUnused (desc);\r
-                    jassertfalse;\r
-                }\r
-\r
-                result.add (std::move (juceUrl));\r
-            }\r
-\r
-            owner.finished (std::move (result));\r
-        }];\r
-    }\r
-\r
-    void didPickDocumentAtURL (NSURL* url)\r
-    {\r
-        didPickDocumentsAtURLs (@[url]);\r
-    }\r
-\r
-    void pickerWasCancelled()\r
-    {\r
-        cancelPendingUpdate();\r
-        owner.finished ({});\r
-        // Calling owner.finished will delete this Pimpl instance, so don't call any more member functions here!\r
-    }\r
-\r
-    //==============================================================================\r
-    struct FileChooserDelegateClass  : public ObjCClass<NSObject<UIDocumentPickerDelegate>>\r
-    {\r
-        FileChooserDelegateClass()  : ObjCClass<NSObject<UIDocumentPickerDelegate>> ("FileChooserDelegate_")\r
-        {\r
-            addIvar<Native*> ("owner");\r
-\r
-            addMethod (@selector (documentPicker:didPickDocumentAtURL:),   didPickDocumentAtURL);\r
-            addMethod (@selector (documentPicker:didPickDocumentsAtURLs:), didPickDocumentsAtURLs);\r
-            addMethod (@selector (documentPickerWasCancelled:),            documentPickerWasCancelled);\r
-\r
-            addProtocol (@protocol (UIDocumentPickerDelegate));\r
-\r
-            registerClass();\r
-        }\r
-\r
-        static void setOwner (id self, Native* owner)   { object_setInstanceVariable (self, "owner", owner); }\r
-        static Native* getOwner (id self)               { return getIvar<Native*> (self, "owner"); }\r
-\r
-        //==============================================================================\r
-        static void didPickDocumentAtURL (id self, SEL, UIDocumentPickerViewController*, NSURL* url)\r
-        {\r
-            if (auto* picker = getOwner (self))\r
-                picker->didPickDocumentAtURL (url);\r
-        }\r
-\r
-        static void didPickDocumentsAtURLs (id self, SEL, UIDocumentPickerViewController*, NSArray<NSURL*>* urls)\r
-        {\r
-            if (auto* picker = getOwner (self))\r
-                picker->didPickDocumentsAtURLs (urls);\r
-        }\r
-\r
-        static void documentPickerWasCancelled (id self, SEL, UIDocumentPickerViewController*)\r
-        {\r
-            if (auto* picker = getOwner (self))\r
-                picker->pickerWasCancelled();\r
-        }\r
-    };\r
-\r
-    struct FileChooserControllerClass  : public ObjCClass<UIDocumentPickerViewController>\r
-    {\r
-        FileChooserControllerClass()  : ObjCClass<UIDocumentPickerViewController> ("FileChooserController_")\r
-        {\r
-            addIvar<Native*> ("owner");\r
-            addMethod (@selector (viewDidDisappear:), viewDidDisappear);\r
-\r
-            registerClass();\r
-        }\r
-\r
-        static void setOwner (id self, Native* owner)   { object_setInstanceVariable (self, "owner", owner); }\r
-        static Native* getOwner (id self)               { return getIvar<Native*> (self, "owner"); }\r
-\r
-        //==============================================================================\r
-        static void viewDidDisappear (id self, SEL, BOOL animated)\r
-        {\r
-            sendSuperclassMessage<void> (self, @selector (viewDidDisappear:), animated);\r
-\r
-            if (auto* picker = getOwner (self))\r
-                picker->triggerAsyncUpdate();\r
-        }\r
-    };\r
-\r
     //==============================================================================\r
     FileChooser& owner;\r
     NSUniquePtr<NSObject<UIDocumentPickerDelegate>> delegate;\r
-    NSUniquePtr<UIDocumentPickerViewController> controller;\r
+    NSUniquePtr<FileChooserControllerClass> controller;\r
     UIViewComponentPeer* peer = nullptr;\r
 \r
-    static FileChooserDelegateClass fileChooserDelegateClass;\r
-    static FileChooserControllerClass fileChooserControllerClass;\r
-\r
     //==============================================================================\r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (Native)\r
 };\r
@@ -402,7 +369,7 @@ bool FileChooser::isPlatformDialogAvailable()
 std::shared_ptr<FileChooser::Pimpl> FileChooser::showPlatformDialog (FileChooser& owner, int flags,\r
                                                                      FilePreviewComponent*)\r
 {\r
-    return std::make_shared<FileChooser::Native> (owner, flags);\r
+    return Native::make (owner, flags);\r
 }\r
 \r
 #if JUCE_DEPRECATION_IGNORED\r
@@ -410,3 +377,59 @@ std::shared_ptr<FileChooser::Pimpl> FileChooser::showPlatformDialog (FileChooser
 #endif\r
 \r
 } // namespace juce\r
+\r
+@implementation FileChooserControllerClass\r
+{\r
+    std::weak_ptr<FileChooser::Native> ptr;\r
+}\r
+\r
+- (void) setParent: (FileChooser::Native*) parent\r
+{\r
+    jassert (parent != nullptr);\r
+    jassert (parent->shared_from_this() != nullptr);\r
+    ptr = parent->weak_from_this();\r
+}\r
+\r
+- (void) viewDidDisappear: (BOOL) animated\r
+{\r
+    [super viewDidDisappear: animated];\r
+\r
+    if (auto nativeParent = ptr.lock())\r
+        nativeParent->triggerAsyncUpdate();\r
+}\r
+\r
+@end\r
+\r
+@implementation FileChooserDelegateClass\r
+{\r
+    FileChooser::Native* owner;\r
+}\r
+\r
+- (id) initWithOwner: (FileChooser::Native*) o\r
+{\r
+    self = [super init];\r
+    owner = o;\r
+    return self;\r
+}\r
+\r
+JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-implementations")\r
+- (void) documentPicker: (UIDocumentPickerViewController*) controller didPickDocumentAtURL: (NSURL*) url\r
+{\r
+    if (owner != nullptr)\r
+        owner->didPickDocumentAtURL (url);\r
+}\r
+JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+\r
+- (void) documentPicker: (UIDocumentPickerViewController*) controller didPickDocumentsAtURLs: (NSArray<NSURL*>*) urls\r
+{\r
+    if (owner != nullptr)\r
+        owner->didPickDocumentsAtURLs (urls);\r
+}\r
+\r
+- (void) documentPickerWasCancelled: (UIDocumentPickerViewController*) controller\r
+{\r
+    if (owner != nullptr)\r
+        owner->pickerWasCancelled();\r
+}\r
+\r
+@end\r
index 5336269156116a385d92acf6d997b8ff962b37b6..33b90e3caf9d66492dc593d5eb7940df64cc3cae 100644 (file)
  #define JUCE_HAS_IOS_POINTER_SUPPORT 0\r
 #endif\r
 \r
+#if defined (__IPHONE_13_4) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_13_4\r
+ #define JUCE_HAS_IOS_HARDWARE_KEYBOARD_SUPPORT 1\r
+#else\r
+ #define JUCE_HAS_IOS_HARDWARE_KEYBOARD_SUPPORT 0\r
+#endif\r
+\r
 namespace juce\r
 {\r
 \r
@@ -69,6 +75,28 @@ static NSArray* getContainerAccessibilityElements (AccessibilityHandler& handler
 \r
 class UIViewComponentPeer;\r
 \r
+namespace iOSGlobals\r
+{\r
+class KeysCurrentlyDown\r
+{\r
+public:\r
+    bool isDown (int x) const { return down.find (x) != down.cend(); }\r
+\r
+    void setDown (int x, bool b)\r
+    {\r
+        if (b)\r
+            down.insert (x);\r
+        else\r
+            down.erase (x);\r
+    }\r
+\r
+private:\r
+    std::set<int> down;\r
+};\r
+static KeysCurrentlyDown keysCurrentlyDown;\r
+static UIViewComponentPeer* currentlyFocusedPeer = nullptr;\r
+} // namespace iOSGlobals\r
+\r
 static UIInterfaceOrientation getWindowOrientation()\r
 {\r
     UIApplication* sharedApplication = [UIApplication sharedApplication];\r
@@ -87,7 +115,7 @@ static UIInterfaceOrientation getWindowOrientation()
     JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
 }\r
 \r
-namespace Orientations\r
+struct Orientations\r
 {\r
     static Desktop::DisplayOrientation convertToJuce (UIInterfaceOrientation orientation)\r
     {\r
@@ -119,8 +147,7 @@ namespace Orientations
         return UIInterfaceOrientationPortrait;\r
     }\r
 \r
-\r
-    static NSUInteger getSupportedOrientations()\r
+    static UIInterfaceOrientationMask getSupportedOrientations()\r
     {\r
         NSUInteger allowed = 0;\r
         auto& d = Desktop::getInstance();\r
@@ -132,7 +159,7 @@ namespace Orientations
 \r
         return allowed;\r
     }\r
-}\r
+};\r
 \r
 enum class MouseEventFlags\r
 {\r
@@ -351,7 +378,7 @@ struct UIViewPeerControllerReceiver
 \r
 //==============================================================================\r
 class UIViewComponentPeer  : public ComponentPeer,\r
-                             private UIViewPeerControllerReceiver\r
+                             public UIViewPeerControllerReceiver\r
 {\r
 public:\r
     UIViewComponentPeer (Component&, int windowStyleFlags, UIView* viewToAttachTo);\r
@@ -404,8 +431,6 @@ public:
     void dismissPendingTextInput() override;\r
     void closeInputMethodContext() override;\r
 \r
-    BOOL textViewReplaceCharacters (Range<int>, const String&);\r
-\r
     void updateScreenBounds();\r
 \r
     void handleTouches (UIEvent*, MouseEventFlags);\r
@@ -415,6 +440,23 @@ public:
     void onScroll (UIPanGestureRecognizer*);\r
    #endif\r
 \r
+    Range<int> getMarkedTextRange() const\r
+    {\r
+        return Range<int>::withStartAndLength (startOfMarkedTextInTextInputTarget,\r
+                                               stringBeingComposed.length());\r
+    }\r
+\r
+    void replaceMarkedRangeWithText (TextInputTarget* target, const String& text)\r
+    {\r
+        if (stringBeingComposed.isNotEmpty())\r
+            target->setHighlightedRegion (getMarkedTextRange());\r
+\r
+        target->insertTextAtCaret (text);\r
+        target->setTemporaryUnderlining ({ Range<int>::withStartAndLength (startOfMarkedTextInTextInputTarget,\r
+                                                                           text.length()) });\r
+        stringBeingComposed = text;\r
+    }\r
+\r
     //==============================================================================\r
     void repaint (const Rectangle<int>& area) override;\r
     void performAnyPendingRepaintsNow() override;\r
@@ -425,6 +467,7 @@ public:
     UIViewController* controller = nil;\r
     const bool isSharedWindow, isAppex;\r
     String stringBeingComposed;\r
+    int startOfMarkedTextInTextInputTarget = 0;\r
     bool fullScreen = false, insideDrawRect = false;\r
     NSUniquePtr<JuceTextView> hiddenTextInput { [[JuceTextView alloc] initWithOwner: this] };\r
     NSUniquePtr<JuceTextInputTokenizer> tokenizer { [[JuceTextInputTokenizer alloc] initWithPeer: this] };\r
@@ -457,9 +500,10 @@ public:
             case TextInputTarget::urlKeyboard:           return UIKeyboardTypeURL;\r
             case TextInputTarget::emailAddressKeyboard:  return UIKeyboardTypeEmailAddress;\r
             case TextInputTarget::phoneNumberKeyboard:   return UIKeyboardTypePhonePad;\r
-            default:                                     jassertfalse; break;\r
+            case TextInputTarget::passwordKeyboard:      return UIKeyboardTypeASCIICapable;\r
         }\r
 \r
+        jassertfalse;\r
         return UIKeyboardTypeDefault;\r
     }\r
 \r
@@ -747,6 +791,178 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
 }\r
 #endif\r
 \r
+static std::optional<int> getKeyCodeForSpecialCharacterString (StringRef characters)\r
+{\r
+    static const auto map = [&]\r
+    {\r
+        std::map<String, int> result\r
+        {\r
+            { nsStringToJuce (UIKeyInputUpArrow),       KeyPress::upKey },\r
+            { nsStringToJuce (UIKeyInputDownArrow),     KeyPress::downKey },\r
+            { nsStringToJuce (UIKeyInputLeftArrow),     KeyPress::leftKey },\r
+            { nsStringToJuce (UIKeyInputRightArrow),    KeyPress::rightKey },\r
+            { nsStringToJuce (UIKeyInputEscape),        KeyPress::escapeKey },\r
+           #if JUCE_HAS_IOS_HARDWARE_KEYBOARD_SUPPORT\r
+            // These symbols are available on iOS 8, but only declared in the headers for iOS 13.4+\r
+            { nsStringToJuce (UIKeyInputPageUp),        KeyPress::pageUpKey },\r
+            { nsStringToJuce (UIKeyInputPageDown),      KeyPress::pageDownKey },\r
+           #endif\r
+        };\r
+\r
+       #if JUCE_HAS_IOS_HARDWARE_KEYBOARD_SUPPORT\r
+        if (@available (iOS 13.4, *))\r
+        {\r
+            result.insert ({ { nsStringToJuce (UIKeyInputHome),          KeyPress::homeKey },\r
+                             { nsStringToJuce (UIKeyInputEnd),           KeyPress::endKey },\r
+                             { nsStringToJuce (UIKeyInputF1),            KeyPress::F1Key },\r
+                             { nsStringToJuce (UIKeyInputF2),            KeyPress::F2Key },\r
+                             { nsStringToJuce (UIKeyInputF3),            KeyPress::F3Key },\r
+                             { nsStringToJuce (UIKeyInputF4),            KeyPress::F4Key },\r
+                             { nsStringToJuce (UIKeyInputF5),            KeyPress::F5Key },\r
+                             { nsStringToJuce (UIKeyInputF6),            KeyPress::F6Key },\r
+                             { nsStringToJuce (UIKeyInputF7),            KeyPress::F7Key },\r
+                             { nsStringToJuce (UIKeyInputF8),            KeyPress::F8Key },\r
+                             { nsStringToJuce (UIKeyInputF9),            KeyPress::F9Key },\r
+                             { nsStringToJuce (UIKeyInputF10),           KeyPress::F10Key },\r
+                             { nsStringToJuce (UIKeyInputF11),           KeyPress::F11Key },\r
+                             { nsStringToJuce (UIKeyInputF12),           KeyPress::F12Key } });\r
+        }\r
+       #endif\r
+\r
+       #if defined (__IPHONE_15_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_15_0\r
+        if (@available (iOS 15.0, *))\r
+        {\r
+            result.insert ({ { nsStringToJuce (UIKeyInputDelete),        KeyPress::deleteKey } });\r
+        }\r
+       #endif\r
+\r
+        return result;\r
+    }();\r
+\r
+    const auto iter = map.find (characters);\r
+    return iter != map.cend() ? std::make_optional (iter->second) : std::nullopt;\r
+}\r
+\r
+static int getKeyCodeForCharacters (StringRef unmodified)\r
+{\r
+    return getKeyCodeForSpecialCharacterString (unmodified).value_or (unmodified[0]);\r
+}\r
+\r
+static int getKeyCodeForCharacters (NSString* characters)\r
+{\r
+    return getKeyCodeForCharacters (nsStringToJuce (characters));\r
+}\r
+\r
+#if JUCE_HAS_IOS_HARDWARE_KEYBOARD_SUPPORT\r
+static void updateModifiers (const UIKeyModifierFlags flags)\r
+{\r
+    const auto convert = [&flags] (UIKeyModifierFlags f, int result) { return (flags & f) != 0 ? result : 0; };\r
+    const auto juceFlags = convert (UIKeyModifierAlphaShift, 0) // capslock modifier currently not implemented\r
+                         | convert (UIKeyModifierShift,      ModifierKeys::shiftModifier)\r
+                         | convert (UIKeyModifierControl,    ModifierKeys::ctrlModifier)\r
+                         | convert (UIKeyModifierAlternate,  ModifierKeys::altModifier)\r
+                         | convert (UIKeyModifierCommand,    ModifierKeys::commandModifier)\r
+                         | convert (UIKeyModifierNumericPad, 0); // numpad modifier currently not implemented\r
+\r
+    ModifierKeys::currentModifiers = ModifierKeys::currentModifiers.withOnlyMouseButtons().withFlags (juceFlags);\r
+}\r
+\r
+API_AVAILABLE (ios(13.4))\r
+static int getKeyCodeForKey (UIKey* key)\r
+{\r
+    return getKeyCodeForCharacters ([key charactersIgnoringModifiers]);\r
+}\r
+\r
+API_AVAILABLE (ios(13.4))\r
+static bool attemptToConsumeKeys (JuceUIView* view, NSSet<UIPress*>* presses)\r
+{\r
+    auto used = false;\r
+\r
+    for (UIPress* press in presses)\r
+    {\r
+        if (auto* key = [press key])\r
+        {\r
+            const auto code = getKeyCodeForKey (key);\r
+            const auto handleCodepoint = [view, &used, code] (juce_wchar codepoint)\r
+            {\r
+                // These both need to fire; no short-circuiting!\r
+                used |= view->owner->handleKeyUpOrDown (true);\r
+                used |= view->owner->handleKeyPress (code, codepoint);\r
+            };\r
+\r
+            if (getKeyCodeForSpecialCharacterString (nsStringToJuce ([key charactersIgnoringModifiers])).has_value())\r
+                handleCodepoint (0);\r
+            else\r
+                for (const auto codepoint : nsStringToJuce ([key characters]))\r
+                    handleCodepoint (codepoint);\r
+        }\r
+    }\r
+\r
+    return used;\r
+}\r
+\r
+- (void) pressesBegan:(NSSet<UIPress*>*) presses withEvent:(UIPressesEvent*) event\r
+{\r
+    const auto handledEvent = [&]\r
+    {\r
+        if (@available (iOS 13.4, *))\r
+        {\r
+            auto isEscape = false;\r
+\r
+            updateModifiers ([event modifierFlags]);\r
+\r
+            for (UIPress* press in presses)\r
+            {\r
+                if (auto* key = [press key])\r
+                {\r
+                    const auto code = getKeyCodeForKey (key);\r
+                    isEscape |= code == KeyPress::escapeKey;\r
+                    iOSGlobals::keysCurrentlyDown.setDown (code, true);\r
+                }\r
+            }\r
+\r
+            return ((isEscape && owner->stringBeingComposed.isEmpty())\r
+                    || owner->findCurrentTextInputTarget() == nullptr)\r
+                   && attemptToConsumeKeys (self, presses);\r
+        }\r
+\r
+        return false;\r
+    }();\r
+\r
+    if (! handledEvent)\r
+        [super pressesBegan: presses withEvent: event];\r
+}\r
+\r
+/*  Returns true if we handled the event. */\r
+static bool doKeysUp (UIViewComponentPeer* owner, NSSet<UIPress*>* presses, UIPressesEvent* event)\r
+{\r
+    if (@available (iOS 13.4, *))\r
+    {\r
+        updateModifiers ([event modifierFlags]);\r
+\r
+        for (UIPress* press in presses)\r
+            if (auto* key = [press key])\r
+                iOSGlobals::keysCurrentlyDown.setDown (getKeyCodeForKey (key), false);\r
+\r
+        return owner->findCurrentTextInputTarget() == nullptr && owner->handleKeyUpOrDown (false);\r
+    }\r
+\r
+    return false;\r
+}\r
+\r
+- (void) pressesEnded:(NSSet<UIPress*>*) presses withEvent:(UIPressesEvent*) event\r
+{\r
+    if (! doKeysUp (owner, presses, event))\r
+        [super pressesEnded: presses withEvent: event];\r
+}\r
+\r
+- (void) pressesCancelled:(NSSet<UIPress*>*) presses withEvent:(UIPressesEvent*) event\r
+{\r
+    if (! doKeysUp (owner, presses, event))\r
+        [super pressesCancelled: presses withEvent: event];\r
+}\r
+#endif\r
+\r
 //==============================================================================\r
 - (BOOL) becomeFirstResponder\r
 {\r
@@ -920,7 +1136,10 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
     const auto rangeToDelete = range.isEmpty() ? range.withStartAndLength (jmax (range.getStart() - 1, 0),\r
                                                                            range.getStart() != 0 ? 1 : 0)\r
                                                : range;\r
+    const auto start = rangeToDelete.getStart();\r
 \r
+    // This ensures that the cursor is at the beginning, rather than the end, of the selection\r
+    target->setHighlightedRegion ({ start, start });\r
     target->setHighlightedRegion (rangeToDelete);\r
     target->insertTextAtCaret ("");\r
 }\r
@@ -930,10 +1149,48 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
     if (owner == nullptr)\r
         return;\r
 \r
-    owner->stringBeingComposed.clear();\r
-\r
     if (auto* target = owner->findCurrentTextInputTarget())\r
-        target->insertTextAtCaret (nsStringToJuce (text));\r
+    {\r
+        // If we're in insertText, it's because there's a focused TextInputTarget,\r
+        // and key presses from pressesBegan and pressesEnded have been composed\r
+        // into a string that is now ready for insertion.\r
+        // Because JUCE has been passing key events to the system for composition, it\r
+        // won't have been processing those key presses itself, so it may not have had\r
+        // a chance to process keys like return/tab/etc.\r
+        // It's not possible to filter out these keys during pressesBegan, because they\r
+        // may form part of a longer composition sequence.\r
+        // e.g. when entering Japanese text, the return key may be used to select an option\r
+        // from the IME menu, and in this situation the return key should not be propagated\r
+        // to the JUCE view.\r
+        // If we receive a special character (return/tab/etc.) in insertText, it can\r
+        // only be because the composition has finished, so we can turn the event into\r
+        // a KeyPress and trust the current TextInputTarget to process it correctly.\r
+        const auto redirectKeyPresses = [&] (juce_wchar codepoint)\r
+        {\r
+            // Simulate a key down\r
+            const auto code = getKeyCodeForCharacters (String::charToString (codepoint));\r
+            iOSGlobals::keysCurrentlyDown.setDown (code, true);\r
+            owner->handleKeyUpOrDown (true);\r
+\r
+            owner->handleKeyPress (code, codepoint);\r
+\r
+            // Simulate a key up\r
+            iOSGlobals::keysCurrentlyDown.setDown (code, false);\r
+            owner->handleKeyUpOrDown (false);\r
+        };\r
+\r
+        if ([text isEqual: @"\n"] || [text isEqual: @"\r"])\r
+            redirectKeyPresses ('\r');\r
+        else if ([text isEqual: @"\t"])\r
+            redirectKeyPresses ('\t');\r
+        else\r
+            owner->replaceMarkedRangeWithText (target, nsStringToJuce (text));\r
+\r
+        target->setTemporaryUnderlining ({});\r
+    }\r
+\r
+    owner->stringBeingComposed.clear();\r
+    owner->startOfMarkedTextInTextInputTarget = 0;\r
 }\r
 \r
 - (BOOL) hasText\r
@@ -972,7 +1229,7 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
 {\r
     if (owner != nullptr && owner->stringBeingComposed.isNotEmpty())\r
         if (auto* target = owner->findCurrentTextInputTarget())\r
-            return [JuceUITextRange withRange: target->getHighlightedRegion()];\r
+            return [JuceUITextRange withRange: owner->getMarkedTextRange()];\r
 \r
     return nil;\r
 }\r
@@ -980,22 +1237,24 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
 - (void) setMarkedText: (NSString*) markedText\r
          selectedRange: (NSRange) selectedRange\r
 {\r
-    ignoreUnused (selectedRange);\r
-\r
     if (owner == nullptr)\r
         return;\r
 \r
-    owner->stringBeingComposed = nsStringToJuce (markedText);\r
+    const auto newMarkedText = nsStringToJuce (markedText);\r
+    const ScopeGuard scope { [&] { owner->stringBeingComposed = newMarkedText; } };\r
 \r
     auto* target = owner->findCurrentTextInputTarget();\r
 \r
     if (target == nullptr)\r
         return;\r
 \r
-    const auto currentHighlight = target->getHighlightedRegion();\r
-    target->insertTextAtCaret (owner->stringBeingComposed);\r
-    target->setHighlightedRegion (currentHighlight.withLength (0));\r
-    target->setHighlightedRegion (currentHighlight.withLength (owner->stringBeingComposed.length()));\r
+    if (owner->stringBeingComposed.isEmpty())\r
+        owner->startOfMarkedTextInTextInputTarget = target->getHighlightedRegion().getStart();\r
+\r
+    owner->replaceMarkedRangeWithText (target, newMarkedText);\r
+\r
+    const auto newSelection = nsRangeToJuce (selectedRange) + owner->startOfMarkedTextInTextInputTarget;\r
+    target->setHighlightedRegion (newSelection);\r
 }\r
 \r
 - (void) unmarkText\r
@@ -1008,8 +1267,10 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
     if (target == nullptr)\r
         return;\r
 \r
-    target->insertTextAtCaret (owner->stringBeingComposed);\r
+    owner->replaceMarkedRangeWithText (target, owner->stringBeingComposed);\r
+    target->setTemporaryUnderlining ({});\r
     owner->stringBeingComposed.clear();\r
+    owner->startOfMarkedTextInTextInputTarget = 0;\r
 }\r
 \r
 - (NSDictionary<NSAttributedStringKey, id>*) markedTextStyle\r
@@ -1309,6 +1570,11 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
     return UITextAutocorrectionTypeNo;\r
 }\r
 \r
+- (UITextSpellCheckingType) spellCheckingType\r
+{\r
+    return UITextSpellCheckingTypeNo;\r
+}\r
+\r
 - (BOOL) canBecomeFirstResponder\r
 {\r
     return YES;\r
@@ -1367,9 +1633,15 @@ MultiTouchMapper<UITouch*> UIViewComponentPeer::currentTouches;
 namespace juce\r
 {\r
 \r
-bool KeyPress::isKeyCurrentlyDown (int)\r
+bool KeyPress::isKeyCurrentlyDown (int keyCode)\r
 {\r
+   #if JUCE_HAS_IOS_HARDWARE_KEYBOARD_SUPPORT\r
+    return iOSGlobals::keysCurrentlyDown.isDown (keyCode)\r
+        || ('A' <= keyCode && keyCode <= 'Z' && iOSGlobals::keysCurrentlyDown.isDown ((int) CharacterFunctions::toLowerCase ((juce_wchar) keyCode)))\r
+        || ('a' <= keyCode && keyCode <= 'z' && iOSGlobals::keysCurrentlyDown.isDown ((int) CharacterFunctions::toUpperCase ((juce_wchar) keyCode)));\r
+   #else\r
     return false;\r
+   #endif\r
 }\r
 \r
 Point<float> juce_lastMousePos;\r
@@ -1391,7 +1663,10 @@ UIViewComponentPeer::UIViewComponentPeer (Component& comp, int windowStyleFlags,
 \r
    #if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS\r
     if (@available (iOS 13, *))\r
-        metalRenderer = std::make_unique<CoreGraphicsMetalLayerRenderer<UIView>> (view, comp.isOpaque());\r
+    {\r
+        metalRenderer = CoreGraphicsMetalLayerRenderer<UIView>::create (view, comp.isOpaque());\r
+        jassert (metalRenderer != nullptr);\r
+    }\r
    #endif\r
 \r
     if ((windowStyleFlags & ComponentPeer::windowRequiresSynchronousCoreGraphicsRendering) == 0)\r
@@ -1428,12 +1703,10 @@ UIViewComponentPeer::UIViewComponentPeer (Component& comp, int windowStyleFlags,
     setVisible (component.isVisible());\r
 }\r
 \r
-static UIViewComponentPeer* currentlyFocusedPeer = nullptr;\r
-\r
 UIViewComponentPeer::~UIViewComponentPeer()\r
 {\r
-    if (currentlyFocusedPeer == this)\r
-        currentlyFocusedPeer = nullptr;\r
+    if (iOSGlobals::currentlyFocusedPeer == this)\r
+        iOSGlobals::currentlyFocusedPeer = nullptr;\r
 \r
     currentTouches.deleteAllTouchesForPeer (this);\r
 \r
@@ -1651,6 +1924,13 @@ void UIViewComponentPeer::handleTouches (UIEvent* event, MouseEventFlags mouseEv
     if (event == nullptr)\r
         return;\r
 \r
+   #if JUCE_HAS_IOS_HARDWARE_KEYBOARD_SUPPORT\r
+    if (@available (iOS 13.4, *))\r
+    {\r
+        updateModifiers ([event modifierFlags]);\r
+    }\r
+   #endif\r
+\r
     NSArray* touches = [[event touchesForView: view] allObjects];\r
 \r
     for (unsigned int i = 0; i < [touches count]; ++i)\r
@@ -1754,8 +2034,10 @@ void UIViewComponentPeer::onScroll (UIPanGestureRecognizer* gesture)
     details.isSmooth = true;\r
     details.isInertial = false;\r
 \r
+    const auto reconstructedMousePosition = convertToPointFloat ([gesture locationInView: view]) - convertToPointFloat (offset);\r
+\r
     handleMouseWheel (MouseInputSource::InputSourceType::touch,\r
-                      convertToPointFloat ([gesture locationInView: view]),\r
+                      reconstructedMousePosition,\r
                       UIViewComponentPeer::getMouseTime ([[NSProcessInfo processInfo] systemUptime]),\r
                       details);\r
 }\r
@@ -1764,12 +2046,12 @@ void UIViewComponentPeer::onScroll (UIPanGestureRecognizer* gesture)
 //==============================================================================\r
 void UIViewComponentPeer::viewFocusGain()\r
 {\r
-    if (currentlyFocusedPeer != this)\r
+    if (iOSGlobals::currentlyFocusedPeer != this)\r
     {\r
-        if (ComponentPeer::isValidPeer (currentlyFocusedPeer))\r
-            currentlyFocusedPeer->handleFocusLoss();\r
+        if (ComponentPeer::isValidPeer (iOSGlobals::currentlyFocusedPeer))\r
+            iOSGlobals::currentlyFocusedPeer->handleFocusLoss();\r
 \r
-        currentlyFocusedPeer = this;\r
+        iOSGlobals::currentlyFocusedPeer = this;\r
 \r
         handleFocusGain();\r
     }\r
@@ -1777,9 +2059,9 @@ void UIViewComponentPeer::viewFocusGain()
 \r
 void UIViewComponentPeer::viewFocusLoss()\r
 {\r
-    if (currentlyFocusedPeer == this)\r
+    if (iOSGlobals::currentlyFocusedPeer == this)\r
     {\r
-        currentlyFocusedPeer = nullptr;\r
+        iOSGlobals::currentlyFocusedPeer = nullptr;\r
         handleFocusLoss();\r
     }\r
 }\r
@@ -1789,7 +2071,7 @@ bool UIViewComponentPeer::isFocused() const
     if (isAppex)\r
         return true;\r
 \r
-    return isSharedWindow ? this == currentlyFocusedPeer\r
+    return isSharedWindow ? this == iOSGlobals::currentlyFocusedPeer\r
                           : (window != nil && [window isKeyWindow]);\r
 }\r
 \r
@@ -1804,6 +2086,10 @@ void UIViewComponentPeer::grabFocus()
 \r
 void UIViewComponentPeer::textInputRequired (Point<int>, TextInputTarget&)\r
 {\r
+    // We need to restart the text input session so that the keyboard can change types if necessary.\r
+    if ([hiddenTextInput.get() isFirstResponder])\r
+        [hiddenTextInput.get() resignFirstResponder];\r
+\r
     [hiddenTextInput.get() becomeFirstResponder];\r
 }\r
 \r
@@ -1825,30 +2111,11 @@ void UIViewComponentPeer::dismissPendingTextInput()
     [hiddenTextInput.get() resignFirstResponder];\r
 }\r
 \r
-BOOL UIViewComponentPeer::textViewReplaceCharacters (Range<int> range, const String& text)\r
-{\r
-    if (auto* target = findCurrentTextInputTarget())\r
-    {\r
-        auto currentSelection = target->getHighlightedRegion();\r
-\r
-        if (range.getLength() == 1 && text.isEmpty()) // (detect backspace)\r
-            if (currentSelection.isEmpty())\r
-                target->setHighlightedRegion (currentSelection.withStart (currentSelection.getStart() - 1));\r
-\r
-        WeakReference<Component> deletionChecker (dynamic_cast<Component*> (target));\r
-\r
-        if (text == "\r" || text == "\n" || text == "\r\n")\r
-            handleKeyPress (KeyPress::returnKey, text[0]);\r
-        else\r
-            target->insertTextAtCaret (text);\r
-    }\r
-\r
-    return NO;\r
-}\r
-\r
 //==============================================================================\r
 void UIViewComponentPeer::displayLinkCallback()\r
 {\r
+    vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
+\r
     if (deferredRepaints.isEmpty())\r
         return;\r
 \r
@@ -1913,6 +2180,40 @@ void Desktop::setKioskComponent (Component* kioskModeComp, bool enableOrDisable,
 \r
 void Desktop::allowedOrientationsChanged()\r
 {\r
+   #if defined (__IPHONE_16_0) && __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_16_0\r
+    if (@available (iOS 16.0, *))\r
+    {\r
+        UIApplication* sharedApplication = [UIApplication sharedApplication];\r
+\r
+        const NSUniquePtr<UIWindowSceneGeometryPreferencesIOS> preferences { [UIWindowSceneGeometryPreferencesIOS alloc] };\r
+        [preferences.get() initWithInterfaceOrientations: Orientations::getSupportedOrientations()];\r
+\r
+        for (UIScene* scene in [sharedApplication connectedScenes])\r
+        {\r
+            if ([scene isKindOfClass: [UIWindowScene class]])\r
+            {\r
+                [static_cast<UIWindowScene*> (scene) requestGeometryUpdateWithPreferences: preferences.get()\r
+                                                                             errorHandler: ^([[maybe_unused]] NSError* error)\r
+                 {\r
+                    // Failed to set the new set of supported orientations.\r
+                    // You may have hit this assertion because you're trying to restrict the supported orientations\r
+                    // of an app that allows multitasking (i.e. the app does not require fullscreen, and supports\r
+                    // all orientations).\r
+                    // iPadOS apps that allow multitasking must support all interface orientations,\r
+                    // so attempting to change the set of supported orientations will fail.\r
+                    // If you hit this assertion in an application that requires fullscreen, it may be because the\r
+                    // set of supported orientations declared in the app's plist doesn't have any entries in common\r
+                    // with the orientations passed to Desktop::setOrientationsEnabled.\r
+                    DBG (nsStringToJuce ([error localizedDescription]));\r
+                    jassertfalse;\r
+                }];\r
+            }\r
+        }\r
+\r
+        return;\r
+    }\r
+   #endif\r
+\r
     // if the current orientation isn't allowed anymore then switch orientations\r
     if (! isOrientationEnabled (getCurrentOrientation()))\r
     {\r
index 4b254a466b21a73c1f53031749f69131a8103df0..6fffc44e701f4ee52c59cc0c1d43502930887c0c 100644 (file)
@@ -480,7 +480,7 @@ public:
         : callback (std::move (cb)),\r
           shouldDeleteThis (deleteOnCompletion)\r
     {\r
-        if (currentlyFocusedPeer != nullptr)\r
+        if (iOSGlobals::currentlyFocusedPeer != nullptr)\r
         {\r
             UIAlertController* alert = [UIAlertController alertControllerWithTitle: juceStringToNS (opts.getTitle())\r
                                                                            message: juceStringToNS (opts.getMessage())\r
@@ -490,9 +490,9 @@ public:
             addButton (alert, opts.getButtonText (1));\r
             addButton (alert, opts.getButtonText (2));\r
 \r
-            [currentlyFocusedPeer->controller presentViewController: alert\r
-                                                           animated: YES\r
-                                                         completion: nil];\r
+            [iOSGlobals::currentlyFocusedPeer->controller presentViewController: alert\r
+                                                                       animated: YES\r
+                                                                     completion: nil];\r
         }\r
         else\r
         {\r
index 7eb7176e17eb2a64f6943af08065007402801f3f..f1e71c00278efa6cb5f0a20e8dcb009f60e1f8e9 100644 (file)
@@ -61,6 +61,8 @@ public:
             xSettings->addListener (this);\r
 \r
         getNativeRealtimeModifiers = []() -> ModifierKeys { return XWindowSystem::getInstance()->getNativeRealtimeModifiers(); };\r
+\r
+        updateVBlankTimer();\r
     }\r
 \r
     ~LinuxComponentPeer() override\r
@@ -369,6 +371,8 @@ public:
 \r
         bounds = parentWindow == 0 ? Desktop::getInstance().getDisplays().physicalToLogical (physicalBounds)\r
                                    : physicalBounds / currentScaleFactor;\r
+\r
+        updateVBlankTimer();\r
     }\r
 \r
     void updateBorderSize()\r
@@ -390,13 +394,22 @@ public:
         }\r
     }\r
 \r
+    bool setWindowAssociation (::Window windowIn)\r
+    {\r
+        clearWindowAssociation();\r
+        association = { this, windowIn };\r
+        return association.isValid();\r
+    }\r
+\r
+    void clearWindowAssociation() { association = {}; }\r
+\r
     //==============================================================================\r
     static bool isActiveApplication;\r
     bool focused = false;\r
 \r
 private:\r
     //==============================================================================\r
-    class LinuxRepaintManager   : public Timer\r
+    class LinuxRepaintManager\r
     {\r
     public:\r
         LinuxRepaintManager (LinuxComponentPeer& p)\r
@@ -405,7 +418,7 @@ private:
         {\r
         }\r
 \r
-        void timerCallback() override\r
+        void dispatchDeferredRepaints()\r
         {\r
             XWindowSystem::getInstance()->processPendingPaintsForWindow (peer.windowH);\r
 \r
@@ -413,32 +426,20 @@ private:
                 return;\r
 \r
             if (! regionsNeedingRepaint.isEmpty())\r
-            {\r
-                stopTimer();\r
                 performAnyPendingRepaintsNow();\r
-            }\r
             else if (Time::getApproximateMillisecondCounter() > lastTimeImageUsed + 3000)\r
-            {\r
-                stopTimer();\r
                 image = Image();\r
-            }\r
         }\r
 \r
         void repaint (Rectangle<int> area)\r
         {\r
-            if (! isTimerRunning())\r
-                startTimer (repaintTimerPeriod);\r
-\r
             regionsNeedingRepaint.add (area * peer.currentScaleFactor);\r
         }\r
 \r
         void performAnyPendingRepaintsNow()\r
         {\r
             if (XWindowSystem::getInstance()->getNumPaintsPendingForWindow (peer.windowH) > 0)\r
-            {\r
-                startTimer (repaintTimerPeriod);\r
                 return;\r
-            }\r
 \r
             auto originalRepaintRegion = regionsNeedingRepaint;\r
             regionsNeedingRepaint.clear();\r
@@ -473,8 +474,6 @@ private:
                     }\r
                 }\r
 \r
-                startTimer (repaintTimerPeriod);\r
-\r
                 RectangleList<int> adjustedList (originalRepaintRegion);\r
                 adjustedList.offsetAll (-totalArea.getX(), -totalArea.getY());\r
 \r
@@ -495,12 +494,9 @@ private:
             }\r
 \r
             lastTimeImageUsed = Time::getApproximateMillisecondCounter();\r
-            startTimer (repaintTimerPeriod);\r
         }\r
 \r
     private:\r
-        enum { repaintTimerPeriod = 1000 / 100 };\r
-\r
         LinuxComponentPeer& peer;\r
         const bool isSemiTransparentWindow;\r
         Image image;\r
@@ -512,6 +508,26 @@ private:
         JUCE_DECLARE_NON_COPYABLE (LinuxRepaintManager)\r
     };\r
 \r
+    class LinuxVBlankManager  : public Timer\r
+    {\r
+    public:\r
+        explicit LinuxVBlankManager (std::function<void()> cb)  : callback (std::move (cb))\r
+        {\r
+            jassert (callback);\r
+        }\r
+\r
+        ~LinuxVBlankManager() override           { stopTimer(); }\r
+\r
+        //==============================================================================\r
+        void timerCallback() override            { callback(); }\r
+\r
+    private:\r
+        std::function<void()> callback;\r
+\r
+        JUCE_DECLARE_NON_COPYABLE (LinuxVBlankManager)\r
+        JUCE_DECLARE_NON_MOVEABLE (LinuxVBlankManager)\r
+    };\r
+\r
     //==============================================================================\r
     template <typename This>\r
     static Point<float> localToGlobal (This& t, Point<float> relativePosition)\r
@@ -554,8 +570,31 @@ private:
         }\r
     }\r
 \r
+    void onVBlank()\r
+    {\r
+        vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
+\r
+        if (repainter != nullptr)\r
+            repainter->dispatchDeferredRepaints();\r
+    }\r
+\r
+    void updateVBlankTimer()\r
+    {\r
+        if (auto* display = Desktop::getInstance().getDisplays().getDisplayForRect (bounds))\r
+        {\r
+            // Some systems fail to set an explicit refresh rate, or ask for a refresh rate of 0\r
+            // (observed on Raspbian Bullseye over VNC). In these situations, use a fallback value.\r
+            const auto newIntFrequencyHz = roundToInt (display->verticalFrequencyHz.value_or (0.0));\r
+            const auto frequencyToUse = newIntFrequencyHz != 0 ? newIntFrequencyHz : 100;\r
+\r
+            if (vBlankManager.getTimerInterval() != frequencyToUse)\r
+                vBlankManager.startTimerHz (frequencyToUse);\r
+        }\r
+    }\r
+\r
     //==============================================================================\r
     std::unique_ptr<LinuxRepaintManager> repainter;\r
+    LinuxVBlankManager vBlankManager { [this]() { onVBlank(); } };\r
 \r
     ::Window windowH = {}, parentWindow = {};\r
     Rectangle<int> bounds;\r
@@ -563,6 +602,7 @@ private:
     bool fullScreen = false, isAlwaysOnTop = false;\r
     double currentScaleFactor = 1.0;\r
     Array<Component*> glRepaintListeners;\r
+    ScopedWindowAssociation association;\r
 \r
     //==============================================================================\r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (LinuxComponentPeer)\r
index 791379c771c2009be7733070924875fa13219429..bfa8f0cb8ac7429a3578e325e942cea753e41cb2 100644 (file)
@@ -35,12 +35,11 @@ class CoreGraphicsMetalLayerRenderer
 {\r
 public:\r
     //==============================================================================\r
-    CoreGraphicsMetalLayerRenderer (ViewType* view, bool isOpaque)\r
+    static auto create (ViewType* view, bool isOpaque)\r
     {\r
-        device.reset (MTLCreateSystemDefaultDevice());\r
-        commandQueue.reset ([device.get() newCommandQueue]);\r
-\r
-        attach (view, isOpaque);\r
+        ObjCObjectHandle<id<MTLDevice>> device { MTLCreateSystemDefaultDevice() };\r
+        return rawToUniquePtr (device != nullptr ? new CoreGraphicsMetalLayerRenderer (device, view, isOpaque)\r
+                                                 : nullptr);\r
     }\r
 \r
     ~CoreGraphicsMetalLayerRenderer()\r
@@ -223,6 +222,16 @@ public:
     }\r
 \r
 private:\r
+    //==============================================================================\r
+    CoreGraphicsMetalLayerRenderer (ObjCObjectHandle<id<MTLDevice>> mtlDevice,\r
+                                    ViewType* view,\r
+                                    bool isOpaque)\r
+        : device (mtlDevice),\r
+          commandQueue ([device.get() newCommandQueue])\r
+    {\r
+        attach (view, isOpaque);\r
+    }\r
+\r
     //==============================================================================\r
     static auto alignTo (size_t n, size_t alignment)\r
     {\r
index 81d8b6d7ed85123290c38067d286410d1658f751..9f6bc9dcdd69bebd89cb54ffa7eaae7ecbe9f2fa 100644 (file)
@@ -279,10 +279,9 @@ private:
                  && ! [[NSWorkspace sharedWorkspace] isFilePackageAtPath: juceStringToNS (f.getFullPathName())];\r
     }\r
 \r
-    void panelSelectionDidChange (id sender)\r
+    void panelSelectionDidChange ([[maybe_unused]] id sender)\r
     {\r
         jassert (sender == panel);\r
-        ignoreUnused (sender);\r
 \r
         // NB: would need to extend FilePreviewComponent to handle the full list rather than just the first one\r
         if (preview != nullptr)\r
index c77a92a9be47747b0cc1c28a3c21b0ea587198fc..0e6ba3e3cbf51dcaf7c818c95ee757c156da1855 100644 (file)
@@ -453,16 +453,12 @@ private:
         {\r
             ValidatorClass()  : ObjCClass ("JUCEMenuValidator_")\r
             {\r
-                addMethod (menuItemInvokedSelector,       menuItemInvoked);\r
-                addMethod (@selector (validateMenuItem:), validateMenuItem);\r
+                addMethod (menuItemInvokedSelector,       [] (id, SEL, NSMenuItem*) {});\r
+                addMethod (@selector (validateMenuItem:), [] (id, SEL, NSMenuItem*) { return YES; });\r
                 addProtocol (@protocol (NSMenuItemValidation));\r
 \r
                 registerClass();\r
             }\r
-\r
-        private:\r
-            static BOOL validateMenuItem (id, SEL, NSMenuItem*)      { return YES; }\r
-            static void menuItemInvoked  (id, SEL, NSMenuItem*)      {}\r
         };\r
 \r
         static ValidatorClass validatorClass;\r
@@ -504,7 +500,7 @@ private:
         return m;\r
     }\r
 \r
-    // Apple Bug: For some reason [NSMenu removeAllItems] seems to leak it's objects\r
+    // Apple Bug: For some reason [NSMenu removeAllItems] seems to leak its objects\r
     // on shutdown, so we need this method to release the items one-by-one manually\r
     static void removeItemRecursive (NSMenu* parentMenu, int menuItemIndex)\r
     {\r
@@ -544,9 +540,24 @@ private:
         {\r
             addIvar<JuceMainMenuHandler*> ("owner");\r
 \r
-            addMethod (menuItemInvokedSelector,       menuItemInvoked);\r
-            addMethod (@selector (menuNeedsUpdate:),  menuNeedsUpdate);\r
-            addMethod (@selector (validateMenuItem:), validateMenuItem);\r
+            addMethod (menuItemInvokedSelector, [] (id self, SEL, NSMenuItem* item)\r
+            {\r
+                if (auto* juceItem = getPopupMenuItem (item))\r
+                    getOwner (self)->invoke (*juceItem, static_cast<int> ([item tag]));\r
+            });\r
+\r
+            addMethod (@selector (menuNeedsUpdate:), [] (id self, SEL, NSMenu* menu)\r
+            {\r
+                getOwner (self)->updateTopLevelMenu (menu);\r
+            });\r
+\r
+            addMethod (@selector (validateMenuItem:), [] (id, SEL, NSMenuItem* item) -> BOOL\r
+            {\r
+                if (auto* juceItem = getPopupMenuItem (item))\r
+                    return juceItem->isEnabled;\r
+\r
+                return YES;\r
+            });\r
 \r
             addProtocol (@protocol (NSMenuDelegate));\r
             addProtocol (@protocol (NSMenuItemValidation));\r
@@ -560,34 +571,15 @@ private:
         }\r
 \r
     private:\r
-        static auto* getPopupMenuItem (NSMenuItem* item)\r
+        static PopupMenu::Item* getPopupMenuItem (NSMenuItem* item)\r
         {\r
             return getJuceClassFromNSObject<PopupMenu::Item> ([item representedObject]);\r
         }\r
 \r
-        static auto* getOwner (id self)\r
+        static JuceMainMenuHandler* getOwner (id self)\r
         {\r
             return getIvar<JuceMainMenuHandler*> (self, "owner");\r
         }\r
-\r
-        static void menuItemInvoked (id self, SEL, NSMenuItem* item)\r
-        {\r
-            if (auto* juceItem = getPopupMenuItem (item))\r
-                getOwner (self)->invoke (*juceItem, static_cast<int> ([item tag]));\r
-        }\r
-\r
-        static void menuNeedsUpdate (id self, SEL, NSMenu* menu)\r
-        {\r
-            getOwner (self)->updateTopLevelMenu (menu);\r
-        }\r
-\r
-        static BOOL validateMenuItem (id, SEL, NSMenuItem* item)\r
-        {\r
-            if (auto* juceItem = getPopupMenuItem (item))\r
-                return juceItem->isEnabled;\r
-\r
-            return YES;\r
-        }\r
     };\r
 };\r
 \r
index 2047f6f91b37e18e02cac12a7edb5f611f52eb50..95321245ca99c4afc5048e9951bcd35c6b33d133 100644 (file)
@@ -151,7 +151,7 @@ public:
       #if USE_COREGRAPHICS_RENDERING\r
        #if JUCE_COREGRAPHICS_RENDER_WITH_MULTIPLE_PAINT_CALLS\r
         if (@available (macOS 10.14, *))\r
-            metalRenderer = std::make_unique<CoreGraphicsMetalLayerRenderer<NSView>> (view, getComponent().isOpaque());\r
+            metalRenderer = CoreGraphicsMetalLayerRenderer<NSView>::create (view, getComponent().isOpaque());\r
        #endif\r
         if ((windowStyleFlags & ComponentPeer::windowRequiresSynchronousCoreGraphicsRendering) == 0)\r
         {\r
@@ -163,8 +163,6 @@ public:
         }\r
       #endif\r
 \r
-        createCVDisplayLink();\r
-\r
         if (isSharedWindow)\r
         {\r
             window = [viewToAttachTo window];\r
@@ -180,6 +178,7 @@ public:
                                                        styleMask: getNSWindowStyleMask (windowStyleFlags)\r
                                                          backing: NSBackingStoreBuffered\r
                                                            defer: YES];\r
+            [window setColorSpace: [NSColorSpace sRGBColorSpace]];\r
             setOwner (window, this);\r
 \r
             if (@available (macOS 10.10, *))\r
@@ -221,7 +220,7 @@ public:
             scopedObservers.emplace_back (view, frameChangedSelector, NSWindowDidMoveNotification, window);\r
             scopedObservers.emplace_back (view, frameChangedSelector, NSWindowDidMiniaturizeNotification, window);\r
             scopedObservers.emplace_back (view, @selector (windowWillMiniaturize:), NSWindowWillMiniaturizeNotification, window);\r
-            scopedObservers.emplace_back (view, @selector (windowDidMiniaturize:), NSWindowDidMiniaturizeNotification, window);\r
+            scopedObservers.emplace_back (view, @selector (windowDidDeminiaturize:), NSWindowDidDeminiaturizeNotification, window);\r
         }\r
 \r
         auto alpha = component.getAlpha();\r
@@ -242,9 +241,6 @@ public:
 \r
     ~NSViewComponentPeer() override\r
     {\r
-        CVDisplayLinkStop (displayLink);\r
-        dispatch_source_cancel (displaySource);\r
-\r
         scopedObservers.clear();\r
 \r
         setOwner (view, nullptr);\r
@@ -415,12 +411,12 @@ public:
         if (forceFullScreen)\r
             return NSWindowCollectionBehaviorFullScreenPrimary;\r
 \r
-        // Some SDK versions don't define NSWindowCollectionBehaviorFullScreenNone\r
-        constexpr auto fullScreenNone = (NSUInteger) (1 << 9);\r
+        // Some SDK versions don't define NSWindowCollectionBehaviorFullScreenAuxiliary\r
+        constexpr auto fullScreenAux = (NSUInteger) (1 << 8);\r
 \r
         return (getStyleFlags() & (windowHasMaximiseButton | windowIsResizable)) == (windowHasMaximiseButton | windowIsResizable)\r
              ? NSWindowCollectionBehaviorFullScreenPrimary\r
-             : fullScreenNone;\r
+             : fullScreenAux;\r
     }\r
 \r
     void setCollectionBehaviour (bool forceFullScreen) const\r
@@ -645,7 +641,7 @@ public:
         return usingCoreGraphics ? 1 : 0;\r
     }\r
 \r
-    void setCurrentRenderingEngine (int index) override\r
+    void setCurrentRenderingEngine ([[maybe_unused]] int index) override\r
     {\r
        #if USE_COREGRAPHICS_RENDERING\r
         if (usingCoreGraphics != (index > 0))\r
@@ -653,8 +649,6 @@ public:
             usingCoreGraphics = index > 0;\r
             [view setNeedsDisplay: true];\r
         }\r
-       #else\r
-        ignoreUnused (index);\r
        #endif\r
     }\r
 \r
@@ -809,10 +803,8 @@ public:
             {\r
                 bool used = false;\r
 \r
-                for (auto u = unicode.getCharPointer(); ! u.isEmpty();)\r
+                for (auto textCharacter : unicode)\r
                 {\r
-                    auto textCharacter = u.getAndAdvance();\r
-\r
                     switch (keyCode)\r
                     {\r
                         case NSLeftArrowFunctionKey:\r
@@ -834,8 +826,8 @@ public:
                             break;\r
                     }\r
 \r
-                    used = handleKeyUpOrDown (true) || used;\r
-                    used = handleKeyPress (keyCode, textCharacter) || used;\r
+                    used |= handleKeyUpOrDown (true);\r
+                    used |= handleKeyPress (keyCode, textCharacter);\r
                 }\r
 \r
                 return used;\r
@@ -1028,6 +1020,12 @@ public:
         return areAnyWindowsInLiveResize();\r
     }\r
 \r
+    void onVBlank()\r
+    {\r
+        vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
+        setNeedsDisplayRectangles();\r
+    }\r
+\r
     void setNeedsDisplayRectangles()\r
     {\r
         if (deferredRepaints.isEmpty())\r
@@ -1200,11 +1198,6 @@ public:
         setNeedsDisplayRectangles();\r
     }\r
 \r
-    void windowDidChangeScreen()\r
-    {\r
-        updateCVDisplayLinkScreen();\r
-    }\r
-\r
     void viewMovedToWindow()\r
     {\r
         if (isSharedWindow)\r
@@ -1224,9 +1217,6 @@ public:
             windowObservers.emplace_back (view, dismissModalsSelector, NSWindowWillMiniaturizeNotification, currentWindow);\r
             windowObservers.emplace_back (view, becomeKeySelector, NSWindowDidBecomeKeyNotification, currentWindow);\r
             windowObservers.emplace_back (view, resignKeySelector, NSWindowDidResignKeyNotification, currentWindow);\r
-            windowObservers.emplace_back (view, @selector (windowDidChangeScreen:), NSWindowDidChangeScreenNotification, currentWindow);\r
-\r
-            updateCVDisplayLinkScreen();\r
         }\r
     }\r
 \r
@@ -1330,9 +1320,9 @@ public:
         if (auto keyCode = getKeyCodeFromEvent (ev))\r
         {\r
             if (isKeyDown)\r
-                keysCurrentlyDown.addIfNotAlreadyThere (keyCode);\r
+                keysCurrentlyDown.insert (keyCode);\r
             else\r
-                keysCurrentlyDown.removeFirstMatchingValue (keyCode);\r
+                keysCurrentlyDown.erase (keyCode);\r
         }\r
     }\r
 \r
@@ -1563,9 +1553,8 @@ public:
     void closeInputMethodContext() override\r
     {\r
         stringBeingComposed.clear();\r
-        const auto* inputContext = [NSTextInputContext currentInputContext];\r
 \r
-        if (inputContext != nil)\r
+        if (const auto* inputContext = [view inputContext])\r
             [inputContext discardMarkedText];\r
     }\r
 \r
@@ -1586,6 +1575,39 @@ public:
             [window setDocumentEdited: b];\r
     }\r
 \r
+    bool sendEventToInputContextOrComponent (NSEvent* ev)\r
+    {\r
+        // We assume that the event will be handled by the IME.\r
+        // Occasionally, the inputContext may be sent key events like cmd+Q, which it will turn\r
+        // into a noop: call and forward to doCommandBySelector:.\r
+        // In this case, the event will be extracted from keyEventBeingHandled and passed to the\r
+        // focused component, and viewCannotHandleEvent will be set depending on whether the event\r
+        // was handled by the component.\r
+        // If the event was *not* handled by the component, and was also not consumed completely by\r
+        // the IME, it's important to return the event to the system for further handling, so that\r
+        // the main menu works as expected.\r
+        viewCannotHandleEvent = false;\r
+        keyEventBeingHandled.reset ([ev retain]);\r
+        const WeakReference ref { this };\r
+        // redirectKeyDown may delete this peer!\r
+        const ScopeGuard scope { [&ref] { if (ref != nullptr) ref->keyEventBeingHandled = nullptr; } };\r
+\r
+        const auto handled = [&]() -> bool\r
+        {\r
+            if (auto* target = findCurrentTextInputTarget())\r
+                if (const auto* inputContext = [view inputContext])\r
+                    return [inputContext handleEvent: ev] && ! viewCannotHandleEvent;\r
+\r
+            return false;\r
+        }();\r
+\r
+        if (handled)\r
+            return true;\r
+\r
+        stringBeingComposed.clear();\r
+        return redirectKeyDown (ev);\r
+    }\r
+\r
     //==============================================================================\r
     NSWindow* window = nil;\r
     NSView* view = nil;\r
@@ -1596,18 +1618,20 @@ public:
    #else\r
     bool usingCoreGraphics = false;\r
    #endif\r
-    bool isZooming = false, isFirstLiveResize = false, textWasInserted = false;\r
+    NSUniquePtr<NSEvent> keyEventBeingHandled;\r
+    bool isFirstLiveResize = false, viewCannotHandleEvent = false;\r
     bool isStretchingTop = false, isStretchingLeft = false, isStretchingBottom = false, isStretchingRight = false;\r
     bool windowRepresentsFile = false;\r
     bool isAlwaysOnTop = false, wasAlwaysOnTop = false;\r
     String stringBeingComposed;\r
+    int startOfMarkedTextInTextInputTarget = 0;\r
 \r
     Rectangle<float> lastSizeBeforeZoom;\r
     RectangleList<float> deferredRepaints;\r
     uint32 lastRepaintTime;\r
 \r
     static ComponentPeer* currentlyFocusedPeer;\r
-    static Array<int> keysCurrentlyDown;\r
+    static std::set<int> keysCurrentlyDown;\r
     static int insideToFrontCall;\r
 \r
     static const SEL dismissModalsSelector;\r
@@ -1618,6 +1642,65 @@ public:
     static const SEL resignKeySelector;\r
 \r
 private:\r
+    JUCE_DECLARE_WEAK_REFERENCEABLE (NSViewComponentPeer)\r
+\r
+    // Note: the OpenGLContext also has a SharedResourcePointer<PerScreenDisplayLinks> to\r
+    // avoid unnecessarily duplicating display-link threads.\r
+    SharedResourcePointer<PerScreenDisplayLinks> sharedDisplayLinks;\r
+\r
+    class AsyncRepainter : private AsyncUpdater\r
+    {\r
+    public:\r
+        explicit AsyncRepainter (NSViewComponentPeer& o) : owner (o) {}\r
+        ~AsyncRepainter() override { cancelPendingUpdate(); }\r
+\r
+        void markUpdated (const CGDirectDisplayID x)\r
+        {\r
+            {\r
+                const std::scoped_lock lock { mutex };\r
+\r
+                if (std::find (backgroundDisplays.cbegin(), backgroundDisplays.cend(), x) == backgroundDisplays.cend())\r
+                    backgroundDisplays.push_back (x);\r
+            }\r
+\r
+            triggerAsyncUpdate();\r
+        }\r
+\r
+    private:\r
+        void handleAsyncUpdate() override\r
+        {\r
+            {\r
+                const std::scoped_lock lock { mutex };\r
+                mainThreadDisplays = backgroundDisplays;\r
+                backgroundDisplays.clear();\r
+            }\r
+\r
+            for (const auto& display : mainThreadDisplays)\r
+                if (auto* peerView = owner.view)\r
+                    if (auto* peerWindow = [peerView window])\r
+                        if (display == ScopedDisplayLink::getDisplayIdForScreen ([peerWindow screen]))\r
+                            owner.onVBlank();\r
+        }\r
+\r
+        NSViewComponentPeer& owner;\r
+        std::mutex mutex;\r
+        std::vector<CGDirectDisplayID> backgroundDisplays, mainThreadDisplays;\r
+    };\r
+\r
+    AsyncRepainter asyncRepainter { *this };\r
+\r
+    /*  Creates a function object that can be called from an arbitrary thread (probably a CVLink\r
+        thread). When called, this function object will trigger a call to setNeedsDisplayRectangles\r
+        as soon as possible on the main thread, for any peers currently on the provided NSScreen.\r
+    */\r
+    PerScreenDisplayLinks::Connection connection\r
+    {\r
+        sharedDisplayLinks->registerFactory ([this] (CGDirectDisplayID display)\r
+        {\r
+            return [this, display] { asyncRepainter.markUpdated (display); };\r
+        })\r
+    };\r
+\r
     static NSView* createViewInstance();\r
     static NSWindow* createWindowInstance();\r
 \r
@@ -1784,48 +1867,6 @@ private:
     }\r
 \r
     //==============================================================================\r
-    void onDisplaySourceCallback()\r
-    {\r
-        setNeedsDisplayRectangles();\r
-    }\r
-\r
-    void onDisplayLinkCallback()\r
-    {\r
-        dispatch_source_merge_data (displaySource, 1);\r
-    }\r
-\r
-    static CVReturn displayLinkCallback (CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*,\r
-                                         CVOptionFlags, CVOptionFlags*, void* context)\r
-    {\r
-        static_cast<NSViewComponentPeer*> (context)->onDisplayLinkCallback();\r
-        return kCVReturnSuccess;\r
-    }\r
-\r
-    void updateCVDisplayLinkScreen()\r
-    {\r
-        auto viewDisplayID = (CGDirectDisplayID) [[window.screen.deviceDescription objectForKey: @"NSScreenNumber"] unsignedIntegerValue];\r
-        auto result = CVDisplayLinkSetCurrentCGDisplay (displayLink, viewDisplayID);\r
-        jassertquiet (result == kCVReturnSuccess);\r
-    }\r
-\r
-    void createCVDisplayLink()\r
-    {\r
-        displaySource = dispatch_source_create (DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, dispatch_get_main_queue());\r
-        dispatch_source_set_event_handler (displaySource, ^(){ onDisplaySourceCallback(); });\r
-        dispatch_resume (displaySource);\r
-\r
-        auto cvReturn = CVDisplayLinkCreateWithActiveCGDisplays (&displayLink);\r
-        jassertquiet (cvReturn == kCVReturnSuccess);\r
-\r
-        cvReturn = CVDisplayLinkSetOutputCallback (displayLink, &displayLinkCallback, this);\r
-        jassertquiet (cvReturn == kCVReturnSuccess);\r
-\r
-        CVDisplayLinkStart (displayLink);\r
-    }\r
-\r
-    CVDisplayLinkRef displayLink = nullptr;\r
-    dispatch_source_t displaySource = nullptr;\r
-\r
     int numFramesToSkipMetalRenderer = 0;\r
     std::unique_ptr<CoreGraphicsMetalLayerRenderer<NSView>> metalRenderer;\r
 \r
@@ -1969,12 +2010,6 @@ struct JuceNSViewClass   : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
             }\r
         });\r
 \r
-        addMethod (@selector (windowDidChangeScreen:), [] (id self, SEL, NSNotification*)\r
-        {\r
-            if (auto* p = getOwner (self))\r
-                p->windowDidChangeScreen();\r
-        });\r
-\r
         addMethod (@selector (wantsDefaultClipping), [] (id, SEL) { return YES; }); // (this is the default, but may want to customise it in future)\r
 \r
         addMethod (@selector (worksWhenModal), [] (id self, SEL)\r
@@ -2000,19 +2035,16 @@ struct JuceNSViewClass   : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
 \r
         addMethod (@selector (keyDown:), [] (id self, SEL, NSEvent* ev)\r
         {\r
-            if (auto* owner = getOwner (self))\r
+            const auto handled = [&]\r
             {\r
-                auto* target = owner->findCurrentTextInputTarget();\r
-                owner->textWasInserted = false;\r
+                if (auto* owner = getOwner (self))\r
+                    return owner->sendEventToInputContextOrComponent (ev);\r
 \r
-                if (target != nullptr)\r
-                    [(NSView*) self interpretKeyEvents: [NSArray arrayWithObject: ev]];\r
-                else\r
-                    owner->stringBeingComposed.clear();\r
+                return false;\r
+            }();\r
 \r
-                if (! (owner->textWasInserted || owner->redirectKeyDown (ev)))\r
-                    sendSuperclassMessage<void> (self, @selector (keyDown:), ev);\r
-            }\r
+            if (! handled)\r
+                sendSuperclassMessage<void> (self, @selector (keyDown:), ev);\r
         });\r
 \r
         addMethod (@selector (keyUp:), [] (id self, SEL, NSEvent* ev)\r
@@ -2023,41 +2055,160 @@ struct JuceNSViewClass   : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
                 sendSuperclassMessage<void> (self, @selector (keyUp:), ev);\r
         });\r
 \r
-        addMethod (@selector (insertText:), [] (id self, SEL, id aString)\r
+        // See "The Path of Key Events" on this page:\r
+        // https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/EventOverview/EventArchitecture/EventArchitecture.html\r
+        // Normally, 'special' key presses (cursor keys, shortcuts, return, delete etc.) will be\r
+        // sent down the view hierarchy to this function before any of the other keyboard handling\r
+        // functions.\r
+        // If any object returns YES from performKeyEquivalent, then the event is consumed.\r
+        // If no object handles the key equivalent, then the event will be sent to the main menu.\r
+        // If the menu is also unable to respond to the event, then the event will be sent\r
+        // to keyDown:/keyUp: via sendEvent:, but this time the event will be sent to the first\r
+        // responder and propagated back up the responder chain.\r
+        // This architecture presents some issues in JUCE apps, which always expect the focused\r
+        // Component to be sent all key presses *including* special keys.\r
+        // There are also some slightly pathological cases that JUCE needs to support, for example\r
+        // the situation where one of the cursor keys is bound to a main menu item. By default,\r
+        // macOS would send the cursor event to performKeyEquivalent on each NSResponder, then send\r
+        // the event to the main menu if no responder handled it. This would mean that the focused\r
+        // Component would never see the event, which would break widgets like the TextEditor, which\r
+        // expect to take precedence over menu items when they have focus.\r
+        // Another layer of subtlety is that some IMEs require cursor key input. When long-pressing\r
+        // the 'e' key to bring up the accent menu, the popup menu should receive cursor events\r
+        // before the focused component.\r
+        // To fulfil all of these requirements, we handle special keys ('key equivalents') like any\r
+        // other key event, and send these events firstly to the NSTextInputContext (if there's an\r
+        // active TextInputTarget), and then on to the focused Component in the case that the\r
+        // input handler is unable to use the keypress. If the event still hasn't been used, then\r
+        // it will be sent to the superclass's performKeyEquivalent: function, which will give the\r
+        // OS a chance to handle events like cmd+Q, cmd+`, cmd+H etc.\r
+        addMethod (@selector (performKeyEquivalent:), [] (id self, SEL s, NSEvent* ev) -> BOOL\r
         {\r
-            // This commits multi-byte text when return is pressed, or after every keypress for western keyboards\r
             if (auto* owner = getOwner (self))\r
-            {\r
-                NSString* newText = [aString isKindOfClass: [NSAttributedString class]] ? [aString string] : aString;\r
+                return owner->sendEventToInputContextOrComponent (ev);\r
+\r
+            return sendSuperclassMessage<BOOL> (self, s, ev);\r
+        });\r
 \r
-                if ([newText length] > 0)\r
+        addMethod (@selector (insertText:replacementRange:), [] (id self, SEL, id aString, NSRange replacementRange)\r
+        {\r
+            // This commits multi-byte text when using an IME, or after every keypress for western keyboards\r
+            if (auto* owner = getOwner (self))\r
+            {\r
+                if (auto* target = owner->findCurrentTextInputTarget())\r
                 {\r
-                    if (auto* target = owner->findCurrentTextInputTarget())\r
+                    const auto newText = nsStringToJuce ([aString isKindOfClass: [NSAttributedString class]] ? [aString string] : aString);\r
+\r
+                    if (newText.isNotEmpty())\r
                     {\r
-                        target->insertTextAtCaret (nsStringToJuce (newText));\r
-                        owner->textWasInserted = true;\r
+                        target->setHighlightedRegion ([&]\r
+                        {\r
+                            // To test this, try long-pressing 'e' to bring up the accent popup,\r
+                            // then select one of the accented options.\r
+                            if (replacementRange.location != NSNotFound)\r
+                                return nsRangeToJuce (replacementRange);\r
+\r
+                            // To test this, try entering the characters 'a b <esc>' with the 2-Set\r
+                            // Korean IME. The input client should receive three calls to setMarkedText:\r
+                            // followed by a call to insertText:\r
+                            // The final call to insertText should overwrite the currently-marked\r
+                            // text, and reset the composition string.\r
+                            if (owner->stringBeingComposed.isNotEmpty())\r
+                                return Range<int>::withStartAndLength (owner->startOfMarkedTextInTextInputTarget,\r
+                                                                       owner->stringBeingComposed.length());\r
+\r
+                            return target->getHighlightedRegion();\r
+                        }());\r
+\r
+                        target->insertTextAtCaret (newText);\r
+                        target->setTemporaryUnderlining ({});\r
                     }\r
                 }\r
+                else\r
+                    jassertfalse; // The system should not attempt to insert text when there is no active TextInputTarget\r
 \r
                 owner->stringBeingComposed.clear();\r
             }\r
         });\r
 \r
-        addMethod (@selector (doCommandBySelector:), [] (id, SEL, SEL) {});\r
+        addMethod (@selector (doCommandBySelector:), [] (id self, SEL, SEL sel)\r
+        {\r
+            const auto handled = [&]\r
+            {\r
+                // 'Special' keys, like backspace, return, tab, and escape, are converted to commands by the system.\r
+                // Components still expect to receive these events as key presses, so we send the currently-processed\r
+                // key event (if any).\r
+                if (auto* owner = getOwner (self))\r
+                {\r
+                    owner->viewCannotHandleEvent = [&]\r
+                    {\r
+                        if (auto* e = owner->keyEventBeingHandled.get())\r
+                        {\r
+                            if ([e type] != NSEventTypeKeyDown && [e type] != NSEventTypeKeyUp)\r
+                                return true;\r
+\r
+                            return ! ([e type] == NSEventTypeKeyDown ? owner->redirectKeyDown (e)\r
+                                                                     : owner->redirectKeyUp (e));\r
+                        }\r
+\r
+                        return true;\r
+                    }();\r
+\r
+                    return ! owner->viewCannotHandleEvent;\r
+                }\r
+\r
+                return false;\r
+            }();\r
 \r
-        addMethod (@selector (setMarkedText:selectedRange:), [] (id self, SEL, id aString, NSRange)\r
+            if (! handled)\r
+                sendSuperclassMessage<void> (self, @selector (doCommandBySelector:), sel);\r
+        });\r
+\r
+        addMethod (@selector (setMarkedText:selectedRange:replacementRange:), [] (id self,\r
+                                                                                  SEL,\r
+                                                                                  id aString,\r
+                                                                                  const NSRange selectedRange,\r
+                                                                                  const NSRange replacementRange)\r
         {\r
             if (auto* owner = getOwner (self))\r
             {\r
-                owner->stringBeingComposed = nsStringToJuce ([aString isKindOfClass: [NSAttributedString class]]\r
-                                                             ? [aString string] : aString);\r
-\r
                 if (auto* target = owner->findCurrentTextInputTarget())\r
                 {\r
-                    auto currentHighlight = target->getHighlightedRegion();\r
-                    target->insertTextAtCaret (owner->stringBeingComposed);\r
-                    target->setHighlightedRegion (currentHighlight.withLength (owner->stringBeingComposed.length()));\r
-                    owner->textWasInserted = true;\r
+                    const auto toInsert = nsStringToJuce ([aString isKindOfClass: [NSAttributedString class]] ? [aString string] : aString);\r
+                    const auto [initialHighlight, marked, finalHighlight] = [&]\r
+                    {\r
+                        if (owner->stringBeingComposed.isNotEmpty())\r
+                        {\r
+                            const auto toReplace = Range<int>::withStartAndLength (owner->startOfMarkedTextInTextInputTarget,\r
+                                                                                   owner->stringBeingComposed.length());\r
+\r
+                            return replacementRange.location != NSNotFound\r
+                                 // There's a composition underway, so replacementRange is relative to the marked text,\r
+                                 // and selectedRange is relative to the inserted string.\r
+                                 ? std::tuple (toReplace,\r
+                                               owner->stringBeingComposed.replaceSection (static_cast<int> (replacementRange.location),\r
+                                                                                          static_cast<int> (replacementRange.length),\r
+                                                                                          toInsert),\r
+                                               nsRangeToJuce (selectedRange) + static_cast<int> (replacementRange.location))\r
+                                 // The replacementRange is invalid, so replace all the marked text.\r
+                                 : std::tuple (toReplace, toInsert, nsRangeToJuce (selectedRange));\r
+                        }\r
+\r
+                        if (replacementRange.location != NSNotFound)\r
+                            // There's no string composition in progress, so replacementRange is relative to the start\r
+                            // of the document.\r
+                            return std::tuple (nsRangeToJuce (replacementRange), toInsert, nsRangeToJuce (selectedRange));\r
+\r
+                        return std::tuple (target->getHighlightedRegion(), toInsert, nsRangeToJuce (selectedRange));\r
+                    }();\r
+\r
+                    owner->stringBeingComposed = marked;\r
+                    owner->startOfMarkedTextInTextInputTarget = initialHighlight.getStart();\r
+\r
+                    target->setHighlightedRegion (initialHighlight);\r
+                    target->insertTextAtCaret (marked);\r
+                    target->setTemporaryUnderlining ({ Range<int>::withStartAndLength (initialHighlight.getStart(), marked.length()) });\r
+                    target->setHighlightedRegion (finalHighlight + owner->startOfMarkedTextInTextInputTarget);\r
                 }\r
             }\r
         });\r
@@ -2071,7 +2222,7 @@ struct JuceNSViewClass   : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
                     if (auto* target = owner->findCurrentTextInputTarget())\r
                     {\r
                         target->insertTextAtCaret (owner->stringBeingComposed);\r
-                        owner->textWasInserted = true;\r
+                        target->setTemporaryUnderlining ({});\r
                     }\r
 \r
                     owner->stringBeingComposed.clear();\r
@@ -2085,21 +2236,20 @@ struct JuceNSViewClass   : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
             return owner != nullptr && owner->stringBeingComposed.isNotEmpty();\r
         });\r
 \r
-        addMethod (@selector (conversationIdentifier), [] (id self, SEL)\r
+        addMethod (@selector (attributedSubstringForProposedRange:actualRange:), [] (id self, SEL, NSRange theRange, NSRangePointer actualRange) -> NSAttributedString*\r
         {\r
-            return (long) (pointer_sized_int) self;\r
-        });\r
+            jassert (theRange.location != NSNotFound);\r
 \r
-        addMethod (@selector (attributedSubstringFromRange:), [] (id self, SEL, NSRange theRange) -> NSAttributedString*\r
-        {\r
             if (auto* owner = getOwner (self))\r
             {\r
                 if (auto* target = owner->findCurrentTextInputTarget())\r
                 {\r
-                    Range<int> r ((int) theRange.location,\r
-                                  (int) (theRange.location + theRange.length));\r
+                    const auto clamped = Range<int> { 0, target->getTotalNumChars() }.constrainRange (nsRangeToJuce (theRange));\r
 \r
-                    return [[[NSAttributedString alloc] initWithString: juceStringToNS (target->getTextInRange (r))] autorelease];\r
+                    if (actualRange != nullptr)\r
+                        *actualRange = juceRangeToNS (clamped);\r
+\r
+                    return [[[NSAttributedString alloc] initWithString: juceStringToNS (target->getTextInRange (clamped))] autorelease];\r
                 }\r
             }\r
 \r
@@ -2110,7 +2260,8 @@ struct JuceNSViewClass   : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
         {\r
             if (auto* owner = getOwner (self))\r
                 if (owner->stringBeingComposed.isNotEmpty())\r
-                    return NSMakeRange (0, (NSUInteger) owner->stringBeingComposed.length());\r
+                    return NSMakeRange (static_cast<NSUInteger> (owner->startOfMarkedTextInTextInputTarget),\r
+                                        static_cast<NSUInteger> (owner->stringBeingComposed.length()));\r
 \r
             return NSMakeRange (NSNotFound, 0);\r
         });\r
@@ -2121,22 +2272,40 @@ struct JuceNSViewClass   : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
             {\r
                 if (auto* target = owner->findCurrentTextInputTarget())\r
                 {\r
-                    auto highlight = target->getHighlightedRegion();\r
+                    const auto highlight = target->getHighlightedRegion();\r
 \r
-                    if (! highlight.isEmpty())\r
-                        return NSMakeRange ((NSUInteger) highlight.getStart(),\r
-                                            (NSUInteger) highlight.getLength());\r
+                    // The accent-selector popup does not show if the selectedRange location is NSNotFound!\r
+                    return NSMakeRange ((NSUInteger) highlight.getStart(),\r
+                                        (NSUInteger) highlight.getLength());\r
                 }\r
             }\r
 \r
             return NSMakeRange (NSNotFound, 0);\r
         });\r
 \r
-        addMethod (@selector (firstRectForCharacterRange:), [] (id self, SEL, NSRange)\r
+        addMethod (@selector (firstRectForCharacterRange:actualRange:), [] (id self, SEL, NSRange range, NSRangePointer actualRange)\r
         {\r
             if (auto* owner = getOwner (self))\r
-                if (auto* comp = dynamic_cast<Component*> (owner->findCurrentTextInputTarget()))\r
-                    return flippedScreenRect (makeNSRect (comp->getScreenBounds()));\r
+            {\r
+                if (auto* target = owner->findCurrentTextInputTarget())\r
+                {\r
+                    if (auto* comp = dynamic_cast<Component*> (target))\r
+                    {\r
+                        const auto codePointRange = range.location == NSNotFound ? Range<int>::emptyRange (target->getCaretPosition())\r
+                                                                                 : nsRangeToJuce (range);\r
+                        const auto clamped = Range<int> { 0, target->getTotalNumChars() }.constrainRange (codePointRange);\r
+\r
+                        if (actualRange != nullptr)\r
+                            *actualRange = juceRangeToNS (clamped);\r
+\r
+                        const auto rect = codePointRange.isEmpty() ? target->getCaretRectangleForCharIndex (codePointRange.getStart())\r
+                                                                   : target->getTextBounds (codePointRange).getRectangle (0);\r
+                        const auto areaOnDesktop = comp->localAreaToGlobal (rect);\r
+\r
+                        return flippedScreenRect (makeNSRect (ScalingHelpers::scaledScreenPosToUnscaled (areaOnDesktop)));\r
+                    }\r
+                }\r
+            }\r
 \r
             return NSZeroRect;\r
         });\r
@@ -2188,47 +2357,12 @@ struct JuceNSViewClass   : public NSViewComponentPeerWrapper<ObjCClass<NSView>>
 \r
         addMethod (@selector (isFlipped), [] (id, SEL) { return true; });\r
 \r
-        addMethod (@selector (performKeyEquivalent:), [] (id self, SEL s, NSEvent* event)\r
-        {\r
-            // We try passing shortcut keys to the currently focused component first.\r
-            // If the component doesn't want the event, we'll fall back to the superclass\r
-            // implementation, which will pass the event to the main menu.\r
-            if (tryPassingKeyEventToPeer (event))\r
-                return YES;\r
-\r
-            return sendSuperclassMessage<BOOL> (self, s, event);\r
-        });\r
-\r
-        addProtocol (@protocol (NSTextInput));\r
+        addProtocol (@protocol (NSTextInputClient));\r
 \r
         registerClass();\r
     }\r
 \r
 private:\r
-    static void updateTrackingAreas (id self, SEL)\r
-    {\r
-        sendSuperclassMessage<void> (self, @selector (updateTrackingAreas));\r
-\r
-        resetTrackingArea (static_cast<NSView*> (self));\r
-    }\r
-\r
-    static bool tryPassingKeyEventToPeer (NSEvent* e)\r
-    {\r
-        if ([e type] != NSEventTypeKeyDown && [e type] != NSEventTypeKeyUp)\r
-            return false;\r
-\r
-        if (auto* focused = Component::getCurrentlyFocusedComponent())\r
-        {\r
-            if (auto* peer = dynamic_cast<NSViewComponentPeer*> (focused->getPeer()))\r
-            {\r
-                return [e type] == NSEventTypeKeyDown ? peer->redirectKeyDown (e)\r
-                                                      : peer->redirectKeyUp (e);\r
-            }\r
-        }\r
-\r
-        return false;\r
-    }\r
-\r
     template <typename Func, typename... Args>\r
     static void callOnOwner (id self, Func&& func, Args&&... args)\r
     {\r
@@ -2362,7 +2496,7 @@ struct JuceNSWindowClass   : public NSViewComponentPeerWrapper<ObjCClass<NSWindo
         {\r
             auto* owner = getOwner (self);\r
 \r
-            if (owner == nullptr || owner->isZooming)\r
+            if (owner == nullptr)\r
                 return proposedFrameSize;\r
 \r
             NSRect frameRect = flippedScreenRect ([(NSWindow*) self frame]);\r
@@ -2473,29 +2607,6 @@ struct JuceNSWindowClass   : public NSViewComponentPeerWrapper<ObjCClass<NSWindo
             return nil;\r
         });\r
 \r
-        // Key events will be processed by the peer's component.\r
-        // If the component is unable to use the event, it will be re-sent\r
-        // to performKeyEquivalent.\r
-        // performKeyEquivalent will send the event to the view's superclass,\r
-        // which will try passing the event to the main menu.\r
-        // If the event still hasn't been processed, it will be passed to the\r
-        // next responder in the chain, which will be the NSWindow for a peer\r
-        // that is on the desktop.\r
-        // If the NSWindow still doesn't handle the event, the Apple docs imply\r
-        // that the event should be sent to the NSApp for processing, but this\r
-        // doesn't seem to happen for keyDown events.\r
-        // Instead, the NSWindow attempts to process the event, fails, and\r
-        // triggers an annoying NSBeep.\r
-        // Overriding keyDown to "handle" the event seems to suppress the beep.\r
-        addMethod (@selector (keyDown:), [] (id, SEL, NSEvent* ev)\r
-        {\r
-            ignoreUnused (ev);\r
-\r
-           #if JUCE_DEBUG_UNHANDLED_KEYPRESSES\r
-            DBG ("unhandled key down event with keycode: " << [ev keyCode]);\r
-           #endif\r
-        });\r
-\r
         addMethod (@selector (window:shouldDragDocumentWithEvent:from:withPasteboard:), [] (id self, SEL, id /*window*/, NSEvent*, NSPoint, NSPasteboard*)\r
         {\r
             if (auto* owner = getOwner (self))\r
@@ -2551,20 +2662,25 @@ NSWindow* NSViewComponentPeer::createWindowInstance()
 \r
 //==============================================================================\r
 ComponentPeer* NSViewComponentPeer::currentlyFocusedPeer = nullptr;\r
-Array<int> NSViewComponentPeer::keysCurrentlyDown;\r
+std::set<int> NSViewComponentPeer::keysCurrentlyDown;\r
 \r
 //==============================================================================\r
 bool KeyPress::isKeyCurrentlyDown (int keyCode)\r
 {\r
-    if (NSViewComponentPeer::keysCurrentlyDown.contains (keyCode))\r
+    const auto isDown = [] (int k)\r
+    {\r
+        return NSViewComponentPeer::keysCurrentlyDown.find (k) != NSViewComponentPeer::keysCurrentlyDown.cend();\r
+    };\r
+\r
+    if (isDown (keyCode))\r
         return true;\r
 \r
     if (keyCode >= 'A' && keyCode <= 'Z'\r
-         && NSViewComponentPeer::keysCurrentlyDown.contains ((int) CharacterFunctions::toLowerCase ((juce_wchar) keyCode)))\r
+         && isDown ((int) CharacterFunctions::toLowerCase ((juce_wchar) keyCode)))\r
         return true;\r
 \r
     if (keyCode >= 'a' && keyCode <= 'z'\r
-         && NSViewComponentPeer::keysCurrentlyDown.contains ((int) CharacterFunctions::toUpperCase ((juce_wchar) keyCode)))\r
+         && isDown ((int) CharacterFunctions::toUpperCase ((juce_wchar) keyCode)))\r
         return true;\r
 \r
     return false;\r
diff --git a/modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h b/modules/juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h
new file mode 100644 (file)
index 0000000..7082db1
--- /dev/null
@@ -0,0 +1,304 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
+   Agreement and JUCE Privacy Policy.\r
+\r
+   End User License Agreement: www.juce.com/juce-7-licence\r
+   Privacy Policy: www.juce.com/juce-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+//==============================================================================\r
+/*\r
+    Forwards NSNotificationCenter callbacks to a std::function<void()>.\r
+*/\r
+class FunctionNotificationCenterObserver\r
+{\r
+public:\r
+    FunctionNotificationCenterObserver (NSNotificationName notificationName,\r
+                                        id objectToObserve,\r
+                                        std::function<void()> callback)\r
+        : onNotification (std::move (callback)),\r
+          observer (observerObject.get(), getSelector(), notificationName, objectToObserve)\r
+    {}\r
+\r
+private:\r
+    struct ObserverClass\r
+    {\r
+        ObserverClass()\r
+        {\r
+            klass.addIvar<FunctionNotificationCenterObserver*> ("owner");\r
+\r
+            klass.addMethod (getSelector(), [] (id self, SEL, NSNotification*)\r
+            {\r
+                getIvar<FunctionNotificationCenterObserver*> (self, "owner")->onNotification();\r
+            });\r
+\r
+            klass.registerClass();\r
+        }\r
+\r
+        NSObject* createInstance() const { return klass.createInstance(); }\r
+\r
+    private:\r
+        ObjCClass<NSObject> klass { "JUCEObserverClass_" };\r
+    };\r
+\r
+    static SEL getSelector()\r
+    {\r
+        JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wundeclared-selector")\r
+        return @selector (notificationFired:);\r
+        JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+    }\r
+\r
+    std::function<void()> onNotification;\r
+\r
+    NSUniquePtr<NSObject> observerObject\r
+    {\r
+        [this]\r
+        {\r
+            static ObserverClass observerClass;\r
+            auto* result = observerClass.createInstance();\r
+            object_setInstanceVariable (result, "owner", this);\r
+            return result;\r
+        }()\r
+    };\r
+\r
+    ScopedNotificationCenterObserver observer;\r
+\r
+    // Instances can't be copied or moved, because 'this' is stored as a member of the ObserverClass\r
+    // object.\r
+    JUCE_DECLARE_NON_COPYABLE (FunctionNotificationCenterObserver)\r
+    JUCE_DECLARE_NON_MOVEABLE (FunctionNotificationCenterObserver)\r
+};\r
+\r
+//==============================================================================\r
+/*\r
+    Manages the lifetime of a CVDisplayLinkRef for a single display, and automatically starts and\r
+    stops it.\r
+*/\r
+class ScopedDisplayLink\r
+{\r
+public:\r
+    static CGDirectDisplayID getDisplayIdForScreen (NSScreen* screen)\r
+    {\r
+        return (CGDirectDisplayID) [[screen.deviceDescription objectForKey: @"NSScreenNumber"] unsignedIntegerValue];\r
+    }\r
+\r
+    ScopedDisplayLink (NSScreen* screenIn, std::function<void()> onCallbackIn)\r
+        : displayId (getDisplayIdForScreen (screenIn)),\r
+          link ([display = displayId]\r
+          {\r
+              CVDisplayLinkRef ptr = nullptr;\r
+              const auto result = CVDisplayLinkCreateWithCGDisplay (display, &ptr);\r
+              jassertquiet (result == kCVReturnSuccess);\r
+              jassertquiet (ptr != nullptr);\r
+              return ptr;\r
+          }()),\r
+          onCallback (std::move (onCallbackIn))\r
+    {\r
+        const auto callback = [] (CVDisplayLinkRef,\r
+                                  const CVTimeStamp*,\r
+                                  const CVTimeStamp*,\r
+                                  CVOptionFlags,\r
+                                  CVOptionFlags*,\r
+                                  void* context) -> int\r
+        {\r
+            static_cast<const ScopedDisplayLink*> (context)->onCallback();\r
+            return kCVReturnSuccess;\r
+        };\r
+\r
+        const auto callbackResult = CVDisplayLinkSetOutputCallback (link.get(), callback, this);\r
+        jassertquiet (callbackResult == kCVReturnSuccess);\r
+\r
+        const auto startResult = CVDisplayLinkStart (link.get());\r
+        jassertquiet (startResult == kCVReturnSuccess);\r
+    }\r
+\r
+    ~ScopedDisplayLink() noexcept\r
+    {\r
+        if (link != nullptr)\r
+            CVDisplayLinkStop (link.get());\r
+    }\r
+\r
+    CGDirectDisplayID getDisplayId() const { return displayId; }\r
+\r
+    double getNominalVideoRefreshPeriodS() const\r
+    {\r
+        const auto nominalVideoRefreshPeriod = CVDisplayLinkGetNominalOutputVideoRefreshPeriod (link.get());\r
+\r
+        if ((nominalVideoRefreshPeriod.flags & kCVTimeIsIndefinite) == 0)\r
+            return (double) nominalVideoRefreshPeriod.timeValue / (double) nominalVideoRefreshPeriod.timeScale;\r
+\r
+        return 0.0;\r
+    }\r
+\r
+private:\r
+    struct DisplayLinkDestructor\r
+    {\r
+        void operator() (CVDisplayLinkRef ptr) const\r
+        {\r
+            if (ptr != nullptr)\r
+                CVDisplayLinkRelease (ptr);\r
+        }\r
+    };\r
+\r
+    CGDirectDisplayID displayId;\r
+    std::unique_ptr<std::remove_pointer_t<CVDisplayLinkRef>, DisplayLinkDestructor> link;\r
+    std::function<void()> onCallback;\r
+\r
+    // Instances can't be copied or moved, because 'this' is passed as context to\r
+    // CVDisplayLinkSetOutputCallback\r
+    JUCE_DECLARE_NON_COPYABLE (ScopedDisplayLink)\r
+    JUCE_DECLARE_NON_MOVEABLE (ScopedDisplayLink)\r
+};\r
+\r
+//==============================================================================\r
+/*\r
+    Holds a ScopedDisplayLink for each screen. When the screen configuration changes, the\r
+    ScopedDisplayLinks will be recreated automatically to match the new configuration.\r
+*/\r
+class PerScreenDisplayLinks\r
+{\r
+public:\r
+    PerScreenDisplayLinks()\r
+    {\r
+        refreshScreens();\r
+    }\r
+\r
+    using RefreshCallback = std::function<void()>;\r
+    using Factory = std::function<RefreshCallback (CGDirectDisplayID)>;\r
+\r
+    /*\r
+        Automatically unregisters a CVDisplayLink callback factory when ~Connection() is called.\r
+    */\r
+    class Connection\r
+    {\r
+    public:\r
+        Connection() = default;\r
+\r
+        Connection (PerScreenDisplayLinks& linksIn, std::list<Factory>::const_iterator it)\r
+            : links (&linksIn), iter (it) {}\r
+\r
+        ~Connection() noexcept\r
+        {\r
+            if (links != nullptr)\r
+                links->unregisterFactory (iter);\r
+        }\r
+\r
+        Connection (const Connection&) = delete;\r
+        Connection& operator= (const Connection&) = delete;\r
+\r
+        Connection (Connection&& other) noexcept\r
+            : links (std::exchange (other.links, nullptr)), iter (other.iter) {}\r
+\r
+        Connection& operator= (Connection&& other) noexcept\r
+        {\r
+            Connection { std::move (other) }.swap (*this);\r
+            return *this;\r
+        }\r
+\r
+    private:\r
+        void swap (Connection& other) noexcept\r
+        {\r
+            std::swap (other.links, links);\r
+            std::swap (other.iter, iter);\r
+        }\r
+\r
+        PerScreenDisplayLinks* links = nullptr;\r
+        std::list<Factory>::const_iterator iter;\r
+    };\r
+\r
+    /*  Stores the provided factory for as long as the returned Connection remains alive.\r
+\r
+        Whenever the screen configuration changes, the factory function will be called for each\r
+        screen. The RefreshCallback returned by the factory will be called every time that screen's\r
+        display link callback fires.\r
+    */\r
+    [[nodiscard]] Connection registerFactory (Factory factory)\r
+    {\r
+        const ScopedLock lock (mutex);\r
+        factories.push_front (std::move (factory));\r
+        refreshScreens();\r
+        return { *this, factories.begin() };\r
+    }\r
+\r
+    double getNominalVideoRefreshPeriodSForScreen (CGDirectDisplayID display) const\r
+    {\r
+        const ScopedLock lock (mutex);\r
+\r
+        for (const auto& link : links)\r
+            if (link.getDisplayId() == display)\r
+                return link.getNominalVideoRefreshPeriodS();\r
+\r
+        return 0.0;\r
+    }\r
+\r
+private:\r
+    void unregisterFactory (std::list<Factory>::const_iterator iter)\r
+    {\r
+        const ScopedLock lock (mutex);\r
+        factories.erase (iter);\r
+        refreshScreens();\r
+    }\r
+\r
+    void refreshScreens()\r
+    {\r
+        auto newLinks = [&]\r
+        {\r
+            std::list<ScopedDisplayLink> result;\r
+\r
+            for (NSScreen* screen in [NSScreen screens])\r
+            {\r
+                std::vector<RefreshCallback> callbacks;\r
+\r
+                for (auto& factory : factories)\r
+                    callbacks.push_back (factory (ScopedDisplayLink::getDisplayIdForScreen (screen)));\r
+\r
+                // This is the callback that will actually fire in response to this screen's display\r
+                // link callback.\r
+                result.emplace_back (screen, [callbacks = std::move (callbacks)]\r
+                {\r
+                    for (const auto& callback : callbacks)\r
+                        callback();\r
+                });\r
+            }\r
+\r
+            return result;\r
+        }();\r
+\r
+        const ScopedLock lock (mutex);\r
+        links = std::move (newLinks);\r
+    }\r
+\r
+    CriticalSection mutex;\r
+    // This is a list rather than a vector so that the iterators are stable, even when items are\r
+    // added/removed from the list. This is important because Connection objects store an iterator\r
+    // internally, and may be created/destroyed arbitrarily.\r
+    std::list<Factory> factories;\r
+    // This is a list rather than a vector because ScopedDisplayLink is non-moveable.\r
+    std::list<ScopedDisplayLink> links;\r
+\r
+    FunctionNotificationCenterObserver screenParamsObserver { NSApplicationDidChangeScreenParametersNotification,\r
+                                                              nullptr,\r
+                                                              [this] { refreshScreens(); } };\r
+};\r
+\r
+} // namespace juce\r
index eb736ded0f6ef025a81aba1676bc6b16254fcf95..aaa892da6c28017fdd4ca5a426ccbddfb698be64 100644 (file)
@@ -446,13 +446,43 @@ Point<float> MouseInputSource::getCurrentRawMousePosition()
     }\r
 }\r
 \r
+static ComponentPeer* findPeerContainingPoint (Point<float> globalPos)\r
+{\r
+    for (int i = 0; i < juce::ComponentPeer::getNumPeers(); ++i)\r
+    {\r
+        auto* peer = juce::ComponentPeer::getPeer (i);\r
+\r
+        if (peer->contains (peer->globalToLocal (globalPos).toInt(), false))\r
+            return peer;\r
+    }\r
+\r
+    return nullptr;\r
+}\r
+\r
 void MouseInputSource::setRawMousePosition (Point<float> newPosition)\r
 {\r
+    const auto oldPosition = Desktop::getInstance().getMainMouseSource().getRawScreenPosition();\r
+\r
     // this rubbish needs to be done around the warp call, to avoid causing a\r
     // bizarre glitch..\r
     CGAssociateMouseAndMouseCursorPosition (false);\r
     CGWarpMouseCursorPosition (convertToCGPoint (newPosition));\r
     CGAssociateMouseAndMouseCursorPosition (true);\r
+\r
+    // Mouse enter and exit events seem to be always generated as a consequence of programmatically\r
+    // moving the mouse. However, when the mouse stays within the same peer no mouse move event is\r
+    // generated, and we lose track of the correct Component under the mouse. Hence, we need to\r
+    // generate this missing event here.\r
+    if (auto* peer = findPeerContainingPoint (newPosition); peer != nullptr\r
+                                                            && peer == findPeerContainingPoint (oldPosition))\r
+    {\r
+        peer->handleMouseEvent (MouseInputSource::InputSourceType::mouse,\r
+                                peer->globalToLocal (newPosition),\r
+                                ModifierKeys::currentModifiers,\r
+                                0.0f,\r
+                                0.0f,\r
+                                Time::currentTimeMillis());\r
+    }\r
 }\r
 \r
 double Desktop::getDefaultMasterScale()\r
@@ -483,7 +513,11 @@ public:
     {\r
         static DelegateClass delegateClass;\r
         delegate.reset ([delegateClass.createInstance() init]);\r
-        observer.emplace (delegate.get(), darkModeSelector, @"AppleInterfaceThemeChangedNotification", nil);\r
+        observer.emplace (delegate.get(),\r
+                          darkModeSelector,\r
+                          @"AppleInterfaceThemeChangedNotification",\r
+                          nil,\r
+                          [NSDistributedNotificationCenter class]);\r
     }\r
 \r
 private:\r
@@ -534,11 +568,11 @@ public:
     {\r
         PMAssertion()  : assertionID (kIOPMNullAssertionID)\r
         {\r
-            IOReturn res = IOPMAssertionCreateWithName (kIOPMAssertionTypePreventUserIdleDisplaySleep,\r
-                                                        kIOPMAssertionLevelOn,\r
-                                                        CFSTR ("JUCE Playback"),\r
-                                                        &assertionID);\r
-            jassert (res == kIOReturnSuccess); ignoreUnused (res);\r
+            [[maybe_unused]] IOReturn res = IOPMAssertionCreateWithName (kIOPMAssertionTypePreventUserIdleDisplaySleep,\r
+                                                                         kIOPMAssertionLevelOn,\r
+                                                                         CFSTR ("JUCE Playback"),\r
+                                                                         &assertionID);\r
+            jassert (res == kIOReturnSuccess);\r
         }\r
 \r
         ~PMAssertion()\r
@@ -750,10 +784,9 @@ void Process::setDockIconVisible (bool isVisible)
 {\r
     ProcessSerialNumber psn { 0, kCurrentProcess };\r
 \r
-    OSStatus err = TransformProcessType (&psn, isVisible ? kProcessTransformToForegroundApplication\r
-                                                         : kProcessTransformToUIElementApplication);\r
+    [[maybe_unused]] OSStatus err = TransformProcessType (&psn, isVisible ? kProcessTransformToForegroundApplication\r
+                                                                          : kProcessTransformToUIElementApplication);\r
     jassert (err == 0);\r
-    ignoreUnused (err);\r
 }\r
 \r
 } // namespace juce\r
index e64459fa74ea25c34adfd36d8f52a82937ac9033..22432627997dfef3e9e07ea58e3490e64caaa605 100644 (file)
@@ -262,7 +262,7 @@ namespace DragAndDropHelpers
 \r
         JobStatus runJob() override\r
         {\r
-            ignoreUnused (OleInitialize (nullptr));\r
+            [[maybe_unused]] const auto result = OleInitialize (nullptr);\r
 \r
             auto* source = new JuceDropSource();\r
             auto* data = new JuceDataObject (&format, &medium);\r
index 4c3df9e46f8787787a44805886ee2d2526e37e27..3165260592280e8cbe22ad10f05c4527e569b81a 100644 (file)
@@ -515,7 +515,7 @@ private:
             struct ScopedCoInitialize\r
             {\r
                 // IUnknown_GetWindow will only succeed when instantiated in a single-thread apartment\r
-                ScopedCoInitialize() { ignoreUnused (CoInitializeEx (nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE)); }\r
+                ScopedCoInitialize() { [[maybe_unused]] const auto result = CoInitializeEx (nullptr, COINIT_APARTMENTTHREADED | COINIT_DISABLE_OLE1DDE); }\r
                 ~ScopedCoInitialize() { CoUninitialize(); }\r
             };\r
 \r
index cb247722a7f9791eb064ac025a3419e4afa8b2ec..6756cfd0d28d241d4a1822753fdd25696f134da1 100644 (file)
@@ -453,10 +453,9 @@ static bool isPerMonitorDPIAwareProcess()
    #endif\r
 }\r
 \r
-static bool isPerMonitorDPIAwareWindow (HWND nativeWindow)\r
+static bool isPerMonitorDPIAwareWindow ([[maybe_unused]] HWND nativeWindow)\r
 {\r
    #if ! JUCE_WIN_PER_MONITOR_DPI_AWARE\r
-    ignoreUnused (nativeWindow);\r
     return false;\r
    #else\r
     setDPIAwareness();\r
@@ -499,30 +498,97 @@ static double getGlobalDPI()
     return (GetDeviceCaps (deviceContext.dc, LOGPIXELSX) + GetDeviceCaps (deviceContext.dc, LOGPIXELSY)) / 2.0;\r
 }\r
 \r
+//==============================================================================\r
+class ScopedSuspendResumeNotificationRegistration\r
+{\r
+    static auto& getFunctions()\r
+    {\r
+        struct Functions\r
+        {\r
+            using Register = HPOWERNOTIFY (WINAPI*) (HANDLE, DWORD);\r
+            using Unregister = BOOL (WINAPI*) (HPOWERNOTIFY);\r
+\r
+            Register registerNotification = (Register) getUser32Function ("RegisterSuspendResumeNotification");\r
+            Unregister unregisterNotification = (Unregister) getUser32Function ("UnregisterSuspendResumeNotification");\r
+\r
+            bool isValid() const { return registerNotification != nullptr && unregisterNotification != nullptr; }\r
+\r
+            Functions() = default;\r
+            JUCE_DECLARE_NON_COPYABLE (Functions)\r
+            JUCE_DECLARE_NON_MOVEABLE (Functions)\r
+        };\r
+\r
+        static const Functions functions;\r
+        return functions;\r
+    }\r
+\r
+public:\r
+    ScopedSuspendResumeNotificationRegistration() = default;\r
+\r
+    explicit ScopedSuspendResumeNotificationRegistration (HWND window)\r
+        : handle (getFunctions().isValid()\r
+                      ? getFunctions().registerNotification (window, DEVICE_NOTIFY_WINDOW_HANDLE)\r
+                      : nullptr)\r
+    {}\r
+\r
+private:\r
+    struct Destructor\r
+    {\r
+        void operator() (HPOWERNOTIFY ptr) const\r
+        {\r
+            if (ptr != nullptr)\r
+                getFunctions().unregisterNotification (ptr);\r
+        }\r
+    };\r
+\r
+    std::unique_ptr<std::remove_pointer_t<HPOWERNOTIFY>, Destructor> handle;\r
+};\r
+\r
 //==============================================================================\r
 class ScopedThreadDPIAwarenessSetter::NativeImpl\r
 {\r
 public:\r
-    explicit NativeImpl (HWND nativeWindow)\r
+    static auto& getFunctions()\r
     {\r
-        ignoreUnused (nativeWindow);\r
+        struct Functions\r
+        {\r
+            SetThreadDPIAwarenessContextFunc setThreadAwareness             = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext");\r
+            GetWindowDPIAwarenessContextFunc getWindowAwareness             = (GetWindowDPIAwarenessContextFunc) getUser32Function ("GetWindowDpiAwarenessContext");\r
+            GetThreadDPIAwarenessContextFunc getThreadAwareness             = (GetThreadDPIAwarenessContextFunc) getUser32Function ("GetThreadDpiAwarenessContext");\r
+            GetAwarenessFromDpiAwarenessContextFunc getAwarenessFromContext = (GetAwarenessFromDpiAwarenessContextFunc) getUser32Function ("GetAwarenessFromDpiAwarenessContext");\r
+\r
+            bool isLoaded() const noexcept\r
+            {\r
+                return setThreadAwareness != nullptr\r
+                    && getWindowAwareness != nullptr\r
+                    && getThreadAwareness != nullptr\r
+                    && getAwarenessFromContext != nullptr;\r
+            }\r
+\r
+            Functions() = default;\r
+            JUCE_DECLARE_NON_COPYABLE (Functions)\r
+            JUCE_DECLARE_NON_MOVEABLE (Functions)\r
+        };\r
 \r
+        static const Functions functions;\r
+        return functions;\r
+    }\r
+\r
+    explicit NativeImpl (HWND nativeWindow [[maybe_unused]])\r
+    {\r
        #if JUCE_WIN_PER_MONITOR_DPI_AWARE\r
-        if (auto* functionSingleton = FunctionSingleton::getInstance())\r
+        if (const auto& functions = getFunctions(); functions.isLoaded())\r
         {\r
-            if (! functionSingleton->isLoaded())\r
-                return;\r
-\r
-            auto dpiAwareWindow = (functionSingleton->getAwarenessFromContext (functionSingleton->getWindowAwareness (nativeWindow))\r
+            auto dpiAwareWindow = (functions.getAwarenessFromContext (functions.getWindowAwareness (nativeWindow))\r
                                    == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware);\r
 \r
-            auto dpiAwareThread = (functionSingleton->getAwarenessFromContext (functionSingleton->getThreadAwareness())\r
+            auto dpiAwareThread = (functions.getAwarenessFromContext (functions.getThreadAwareness())\r
                                    == DPI_Awareness::DPI_Awareness_Per_Monitor_Aware);\r
 \r
             if (dpiAwareWindow && ! dpiAwareThread)\r
-                oldContext = functionSingleton->setThreadAwareness (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);\r
+                oldContext = functions.setThreadAwareness (DPI_AWARENESS_CONTEXT_PER_MONITOR_AWARE);\r
             else if (! dpiAwareWindow && dpiAwareThread)\r
-                oldContext = functionSingleton->setThreadAwareness (DPI_AWARENESS_CONTEXT_UNAWARE);\r
+                oldContext = functions.setThreadAwareness (DPI_AWARENESS_CONTEXT_UNAWARE);\r
         }\r
        #endif\r
     }\r
@@ -530,44 +596,16 @@ public:
     ~NativeImpl()\r
     {\r
         if (oldContext != nullptr)\r
-            if (auto* functionSingleton = FunctionSingleton::getInstance())\r
-                functionSingleton->setThreadAwareness (oldContext);\r
+            getFunctions().setThreadAwareness (oldContext);\r
     }\r
 \r
 private:\r
-    struct FunctionSingleton  : public DeletedAtShutdown\r
-    {\r
-        FunctionSingleton() = default;\r
-        ~FunctionSingleton() override { clearSingletonInstance(); }\r
-\r
-        SetThreadDPIAwarenessContextFunc setThreadAwareness             = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext");\r
-        GetWindowDPIAwarenessContextFunc getWindowAwareness             = (GetWindowDPIAwarenessContextFunc) getUser32Function ("GetWindowDpiAwarenessContext");\r
-        GetThreadDPIAwarenessContextFunc getThreadAwareness             = (GetThreadDPIAwarenessContextFunc) getUser32Function ("GetThreadDpiAwarenessContext");\r
-        GetAwarenessFromDpiAwarenessContextFunc getAwarenessFromContext = (GetAwarenessFromDpiAwarenessContextFunc) getUser32Function ("GetAwarenessFromDpiAwarenessContext");\r
-\r
-        bool isLoaded() const noexcept\r
-        {\r
-            return setThreadAwareness != nullptr\r
-                && getWindowAwareness != nullptr\r
-                && getThreadAwareness != nullptr\r
-                && getAwarenessFromContext != nullptr;\r
-        }\r
-\r
-        JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL (FunctionSingleton)\r
-\r
-        JUCE_DECLARE_NON_COPYABLE (FunctionSingleton)\r
-        JUCE_DECLARE_NON_MOVEABLE (FunctionSingleton)\r
-    };\r
-\r
     DPI_AWARENESS_CONTEXT oldContext = nullptr;\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeImpl)\r
     JUCE_DECLARE_NON_MOVEABLE (NativeImpl)\r
 };\r
 \r
-\r
-JUCE_IMPLEMENT_SINGLETON (ScopedThreadDPIAwarenessSetter::NativeImpl::FunctionSingleton)\r
-\r
 ScopedThreadDPIAwarenessSetter::ScopedThreadDPIAwarenessSetter (void* nativeWindow)\r
 {\r
     pimpl = std::make_unique<NativeImpl> ((HWND) nativeWindow);\r
@@ -575,17 +613,31 @@ ScopedThreadDPIAwarenessSetter::ScopedThreadDPIAwarenessSetter (void* nativeWind
 \r
 ScopedThreadDPIAwarenessSetter::~ScopedThreadDPIAwarenessSetter() = default;\r
 \r
+static auto& getScopedDPIAwarenessDisablerFunctions()\r
+{\r
+    struct Functions\r
+    {\r
+        GetThreadDPIAwarenessContextFunc localGetThreadDpiAwarenessContext = (GetThreadDPIAwarenessContextFunc) getUser32Function ("GetThreadDpiAwarenessContext");\r
+        GetAwarenessFromDpiAwarenessContextFunc localGetAwarenessFromDpiAwarenessContextFunc = (GetAwarenessFromDpiAwarenessContextFunc) getUser32Function ("GetAwarenessFromDpiAwarenessContext");\r
+        SetThreadDPIAwarenessContextFunc localSetThreadDPIAwarenessContext = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext");\r
+\r
+        Functions() = default;\r
+        JUCE_DECLARE_NON_COPYABLE (Functions)\r
+        JUCE_DECLARE_NON_MOVEABLE (Functions)\r
+    };\r
+\r
+    static const Functions functions;\r
+    return functions;\r
+}\r
+\r
 ScopedDPIAwarenessDisabler::ScopedDPIAwarenessDisabler()\r
 {\r
-    static auto localGetThreadDpiAwarenessContext            = (GetThreadDPIAwarenessContextFunc)        getUser32Function ("GetThreadDpiAwarenessContext");\r
-    static auto localGetAwarenessFromDpiAwarenessContextFunc = (GetAwarenessFromDpiAwarenessContextFunc) getUser32Function ("GetAwarenessFromDpiAwarenessContext");\r
+    const auto& functions = getScopedDPIAwarenessDisablerFunctions();\r
 \r
-    if (! isPerMonitorDPIAwareThread (localGetThreadDpiAwarenessContext, localGetAwarenessFromDpiAwarenessContextFunc))\r
+    if (! isPerMonitorDPIAwareThread (functions.localGetThreadDpiAwarenessContext, functions.localGetAwarenessFromDpiAwarenessContextFunc))\r
         return;\r
 \r
-    static auto localSetThreadDPIAwarenessContext = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext");\r
-\r
-    if (localSetThreadDPIAwarenessContext != nullptr)\r
+    if (auto* localSetThreadDPIAwarenessContext = functions.localSetThreadDPIAwarenessContext)\r
     {\r
         previousContext = localSetThreadDPIAwarenessContext (DPI_AWARENESS_CONTEXT_UNAWARE);\r
 \r
@@ -599,9 +651,7 @@ ScopedDPIAwarenessDisabler::~ScopedDPIAwarenessDisabler()
 {\r
     if (previousContext != nullptr)\r
     {\r
-        static auto localSetThreadDPIAwarenessContext = (SetThreadDPIAwarenessContextFunc) getUser32Function ("SetThreadDpiAwarenessContext");\r
-\r
-        if (localSetThreadDPIAwarenessContext != nullptr)\r
+        if (auto* localSetThreadDPIAwarenessContext = getScopedDPIAwarenessDisablerFunctions().localSetThreadDPIAwarenessContext)\r
             localSetThreadDPIAwarenessContext ((DPI_AWARENESS_CONTEXT) previousContext);\r
 \r
        #if JUCE_DEBUG\r
@@ -663,17 +713,7 @@ JUCE_API double getScaleFactorForWindow (HWND h)
 {\r
     // NB. Using a local function here because we need to call this method from the plug-in wrappers\r
     // which don't load the DPI-awareness functions on startup\r
-    static GetDPIForWindowFunc localGetDPIForWindow = nullptr;\r
-\r
-    static bool hasChecked = false;\r
-\r
-    if (! hasChecked)\r
-    {\r
-        hasChecked = true;\r
-\r
-        if (localGetDPIForWindow == nullptr)\r
-            localGetDPIForWindow = (GetDPIForWindowFunc) getUser32Function ("GetDpiForWindow");\r
-    }\r
+    static auto localGetDPIForWindow = (GetDPIForWindowFunc) getUser32Function ("GetDpiForWindow");\r
 \r
     if (localGetDPIForWindow != nullptr)\r
         return (double) localGetDPIForWindow (h) / USER_DEFAULT_SCREEN_DPI;\r
@@ -1113,6 +1153,13 @@ Image createSnapshotOfNativeWindow (void* nativeWindowHandle)
 //==============================================================================\r
 namespace IconConverters\r
 {\r
+    struct IconDestructor\r
+    {\r
+        void operator() (HICON ptr) const { if (ptr != nullptr) DestroyIcon (ptr); }\r
+    };\r
+\r
+    using IconPtr = std::unique_ptr<std::remove_pointer_t<HICON>, IconDestructor>;\r
+\r
     static Image createImageFromHICON (HICON icon)\r
     {\r
         if (icon == nullptr)\r
@@ -1381,10 +1428,7 @@ static HMONITOR getMonitorFromOutput (ComSmartPtr<IDXGIOutput> output)
         : desc.Monitor;\r
 }\r
 \r
-struct VBlankListener\r
-{\r
-    virtual void onVBlank() = 0;\r
-};\r
+using VBlankListener = ComponentPeer::VBlankListener;\r
 \r
 //==============================================================================\r
 class VSyncThread : private Thread,\r
@@ -1399,7 +1443,7 @@ public:
           monitor (mon)\r
     {\r
         listeners.push_back (listener);\r
-        startThread (10);\r
+        startThread (Priority::highest);\r
     }\r
 \r
     ~VSyncThread() override\r
@@ -1615,6 +1659,31 @@ private:
 \r
 JUCE_IMPLEMENT_SINGLETON (VBlankDispatcher)\r
 \r
+//==============================================================================\r
+class SimpleTimer  : private Timer\r
+{\r
+public:\r
+    SimpleTimer (int intervalMs, std::function<void()> callbackIn)\r
+        : callback (std::move (callbackIn))\r
+    {\r
+        jassert (callback);\r
+        startTimer (intervalMs);\r
+    }\r
+\r
+    ~SimpleTimer() override\r
+    {\r
+        stopTimer();\r
+    }\r
+\r
+private:\r
+    void timerCallback() override\r
+    {\r
+        callback();\r
+    }\r
+\r
+    std::function<void()> callback;\r
+};\r
+\r
 //==============================================================================\r
 class HWNDComponentPeer  : public ComponentPeer,\r
                            private VBlankListener,\r
@@ -1656,12 +1725,18 @@ public:
             return ModifierKeys::currentModifiers;\r
         };\r
 \r
-        if (updateCurrentMonitor())\r
-            VBlankDispatcher::getInstance()->updateDisplay (*this, currentMonitor);\r
+        updateCurrentMonitorAndRefreshVBlankDispatcher();\r
+\r
+        if (parentToAddTo != nullptr)\r
+            monitorUpdateTimer.emplace (1000, [this] { updateCurrentMonitorAndRefreshVBlankDispatcher(); });\r
+\r
+        suspendResumeRegistration = ScopedSuspendResumeNotificationRegistration { hwnd };\r
     }\r
 \r
     ~HWNDComponentPeer() override\r
     {\r
+        suspendResumeRegistration = {};\r
+\r
         VBlankDispatcher::getInstance()->removeListener (*this);\r
 \r
         // do this first to avoid messages arriving for this window before it's destroyed\r
@@ -1675,9 +1750,6 @@ public:
 \r
         callFunctionIfNotLocked (&destroyWindowCallback, (void*) hwnd);\r
 \r
-        if (currentWindowIcon != nullptr)\r
-            DestroyIcon (currentWindowIcon);\r
-\r
         if (dropTarget != nullptr)\r
         {\r
             dropTarget->peerIsDeleted = true;\r
@@ -2072,6 +2144,7 @@ public:
     //==============================================================================\r
     void onVBlank() override\r
     {\r
+        vBlankListeners.call ([] (auto& l) { l.onVBlank(); });\r
         dispatchDeferredRepaints();\r
     }\r
 \r
@@ -2223,8 +2296,7 @@ public:
                 nameBuffer.clear();\r
                 nameBuffer.resize (bufferSize + 1, 0); // + 1 for the null terminator\r
 \r
-                const auto readCharacters = DragQueryFile (dropFiles, i, nameBuffer.data(), (UINT) nameBuffer.size());\r
-                ignoreUnused (readCharacters);\r
+                [[maybe_unused]] const auto readCharacters = DragQueryFile (dropFiles, i, nameBuffer.data(), (UINT) nameBuffer.size());\r
                 jassert (readCharacters == bufferSize);\r
 \r
                 dragInfo.files.add (String (nameBuffer.data()));\r
@@ -2315,7 +2387,7 @@ private:
     bool fullScreen = false, isDragging = false, isMouseOver = false,\r
          hasCreatedCaret = false, constrainerIsResizing = false;\r
     BorderSize<int> windowBorder;\r
-    HICON currentWindowIcon = nullptr;\r
+    IconConverters::IconPtr currentWindowIcon;\r
     FileDropTarget* dropTarget = nullptr;\r
     uint8 updateLayeredWindowAlpha = 255;\r
     UWPUIViewSettings uwpViewSettings;\r
@@ -2377,7 +2449,6 @@ private:
 \r
             TCHAR moduleFile[1024] = {};\r
             GetModuleFileName (moduleHandle, moduleFile, 1024);\r
-            WORD iconNum = 0;\r
 \r
             WNDCLASSEX wcex = {};\r
             wcex.cbSize         = sizeof (wcex);\r
@@ -2386,9 +2457,13 @@ private:
             wcex.lpszClassName  = windowClassName.toWideCharPointer();\r
             wcex.cbWndExtra     = 32;\r
             wcex.hInstance      = moduleHandle;\r
-            wcex.hIcon          = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum);\r
-            iconNum = 1;\r
-            wcex.hIconSm        = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum);\r
+\r
+            for (const auto& [index, field, ptr] : { std::tuple { 0, &wcex.hIcon,   &iconBig },\r
+                                                     std::tuple { 1, &wcex.hIconSm, &iconSmall } })\r
+            {\r
+                auto iconNum = static_cast<WORD> (index);\r
+                ptr->reset (*field = ExtractAssociatedIcon (moduleHandle, moduleFile, &iconNum));\r
+            }\r
 \r
             atom = RegisterClassEx (&wcex);\r
             jassert (atom != 0);\r
@@ -2483,6 +2558,8 @@ private:
             return false;\r
         }\r
 \r
+        IconConverters::IconPtr iconBig, iconSmall;\r
+\r
         JUCE_DECLARE_NON_COPYABLE (WindowClassHolder)\r
     };\r
 \r
@@ -2668,15 +2745,11 @@ private:
 \r
     void setIcon (const Image& newIcon) override\r
     {\r
-        if (auto hicon = IconConverters::createHICONFromImage (newIcon, TRUE, 0, 0))\r
+        if (IconConverters::IconPtr hicon { IconConverters::createHICONFromImage (newIcon, TRUE, 0, 0) })\r
         {\r
-            SendMessage (hwnd, WM_SETICON, ICON_BIG, (LPARAM) hicon);\r
-            SendMessage (hwnd, WM_SETICON, ICON_SMALL, (LPARAM) hicon);\r
-\r
-            if (currentWindowIcon != nullptr)\r
-                DestroyIcon (currentWindowIcon);\r
-\r
-            currentWindowIcon = hicon;\r
+            SendMessage (hwnd, WM_SETICON, ICON_BIG,   reinterpret_cast<LPARAM> (hicon.get()));\r
+            SendMessage (hwnd, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM> (hicon.get()));\r
+            currentWindowIcon = std::move (hicon);\r
         }\r
     }\r
 \r
@@ -2684,7 +2757,9 @@ private:
     {\r
         using ChangeWindowMessageFilterExFunc = BOOL (WINAPI*) (HWND, UINT, DWORD, PVOID);\r
 \r
-        if (auto changeMessageFilter = (ChangeWindowMessageFilterExFunc) getUser32Function ("ChangeWindowMessageFilterEx"))\r
+        static auto changeMessageFilter = (ChangeWindowMessageFilterExFunc) getUser32Function ("ChangeWindowMessageFilterEx");\r
+\r
+        if (changeMessageFilter != nullptr)\r
         {\r
             changeMessageFilter (hwnd, WM_DROPFILES, 1 /*MSGFLT_ALLOW*/, nullptr);\r
             changeMessageFilter (hwnd, WM_COPYDATA, 1 /*MSGFLT_ALLOW*/, nullptr);\r
@@ -2811,7 +2886,7 @@ private:
                 CombineRgn (rgn, rgn, clipRgn, RGN_AND);\r
                 DeleteObject (clipRgn);\r
 \r
-                std::aligned_storage<8192, alignof (RGNDATA)>::type rgnData;\r
+                std::aligned_storage_t<8192, alignof (RGNDATA)> rgnData;\r
                 const DWORD res = GetRegionData (rgn, sizeof (rgnData), (RGNDATA*) &rgnData);\r
 \r
                 if (res > 0 && res <= sizeof (rgnData))\r
@@ -2909,10 +2984,8 @@ private:
     }\r
    #endif\r
 \r
-    void setCurrentRenderingEngine (int index) override\r
+    void setCurrentRenderingEngine ([[maybe_unused]] int index) override\r
     {\r
-        ignoreUnused (index);\r
-\r
        #if JUCE_DIRECT2D\r
         if (getAvailableRenderingEngines().size() > 1)\r
         {\r
@@ -3481,7 +3554,7 @@ private:
                         const UINT keyChar  = MapVirtualKey ((UINT) key, 2);\r
                         const UINT scanCode = MapVirtualKey ((UINT) key, 0);\r
                         BYTE keyState[256];\r
-                        ignoreUnused (GetKeyboardState (keyState));\r
+                        [[maybe_unused]] const auto state = GetKeyboardState (keyState);\r
 \r
                         WCHAR text[16] = { 0 };\r
                         if (ToUnicode ((UINT) key, scanCode, keyState, text, 8, 0) != 1)\r
@@ -3649,10 +3722,18 @@ private:
         return 0;\r
     }\r
 \r
-    bool updateCurrentMonitor()\r
+    enum class ForceRefreshDispatcher\r
+    {\r
+        no,\r
+        yes\r
+    };\r
+\r
+    void updateCurrentMonitorAndRefreshVBlankDispatcher (ForceRefreshDispatcher force = ForceRefreshDispatcher::no)\r
     {\r
         auto monitor = MonitorFromWindow (hwnd, MONITOR_DEFAULTTONULL);\r
-        return std::exchange (currentMonitor, monitor) != monitor;\r
+\r
+        if (std::exchange (currentMonitor, monitor) != monitor || force == ForceRefreshDispatcher::yes)\r
+            VBlankDispatcher::getInstance()->updateDisplay (*this, currentMonitor);\r
     }\r
 \r
     bool handlePositionChanged()\r
@@ -3671,9 +3752,7 @@ private:
         }\r
 \r
         handleMovedOrResized();\r
-\r
-        if (updateCurrentMonitor())\r
-            VBlankDispatcher::getInstance()->updateDisplay (*this, currentMonitor);\r
+        updateCurrentMonitorAndRefreshVBlankDispatcher();\r
 \r
         return ! dontRepaint; // to allow non-accelerated openGL windows to draw themselves correctly.\r
     }\r
@@ -3831,8 +3910,7 @@ private:
 \r
         auto* dispatcher = VBlankDispatcher::getInstance();\r
         dispatcher->reconfigureDisplays();\r
-        updateCurrentMonitor();\r
-        dispatcher->updateDisplay (*this, currentMonitor);\r
+        updateCurrentMonitorAndRefreshVBlankDispatcher (ForceRefreshDispatcher::yes);\r
     }\r
 \r
     //==============================================================================\r
@@ -4598,6 +4676,8 @@ private:
     bool shouldIgnoreModalDismiss = false;\r
 \r
     RectangleList<int> deferredRepaints;\r
+    ScopedSuspendResumeNotificationRegistration suspendResumeRegistration;\r
+    std::optional<SimpleTimer> monitorUpdateTimer;\r
 \r
     //==============================================================================\r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (HWNDComponentPeer)\r
@@ -5367,27 +5447,23 @@ void Displays::findDisplays (float masterScale)
 }\r
 \r
 //==============================================================================\r
-static HICON extractFileHICON (const File& file)\r
+static auto extractFileHICON (const File& file)\r
 {\r
     WORD iconNum = 0;\r
     WCHAR name[MAX_PATH * 2];\r
     file.getFullPathName().copyToUTF16 (name, sizeof (name));\r
 \r
-    return ExtractAssociatedIcon ((HINSTANCE) Process::getCurrentModuleInstanceHandle(),\r
-                                  name, &iconNum);\r
+    return IconConverters::IconPtr { ExtractAssociatedIcon ((HINSTANCE) Process::getCurrentModuleInstanceHandle(),\r
+                                                            name,\r
+                                                            &iconNum) };\r
 }\r
 \r
 Image juce_createIconForFile (const File& file)\r
 {\r
-    Image image;\r
+    if (const auto icon = extractFileHICON (file))\r
+        return IconConverters::createImageFromHICON (icon.get());\r
 \r
-    if (auto icon = extractFileHICON (file))\r
-    {\r
-        image = IconConverters::createImageFromHICON (icon);\r
-        DestroyIcon (icon);\r
-    }\r
-\r
-    return image;\r
+    return {};\r
 }\r
 \r
 //==============================================================================\r
@@ -5435,12 +5511,6 @@ private:
     public:\r
         explicit ImageImpl (const CustomMouseCursorInfo& infoIn) : info (infoIn) {}\r
 \r
-        ~ImageImpl() override\r
-        {\r
-            for (auto& pair : cursorsBySize)\r
-                DestroyCursor (pair.second);\r
-        }\r
-\r
         HCURSOR getCursor (ComponentPeer& peer) override\r
         {\r
             JUCE_ASSERT_MESSAGE_THREAD;\r
@@ -5451,7 +5521,7 @@ private:
             const auto iter = cursorsBySize.find (size);\r
 \r
             if (iter != cursorsBySize.end())\r
-                return iter->second;\r
+                return iter->second.get();\r
 \r
             const auto logicalSize = info.image.getScaledBounds();\r
             const auto scale = (float) size / (float) unityCursorSize;\r
@@ -5466,12 +5536,19 @@ private:
             const auto hx = jlimit (0, rescaled.getWidth(),  roundToInt ((float) info.hotspot.x * effectiveScale));\r
             const auto hy = jlimit (0, rescaled.getHeight(), roundToInt ((float) info.hotspot.y * effectiveScale));\r
 \r
-            return cursorsBySize.emplace (size, IconConverters::createHICONFromImage (rescaled, false, hx, hy)).first->second;\r
+            return cursorsBySize.emplace (size, CursorPtr { IconConverters::createHICONFromImage (rescaled, false, hx, hy) }).first->second.get();\r
         }\r
 \r
     private:\r
+        struct CursorDestructor\r
+        {\r
+            void operator() (HCURSOR ptr) const { if (ptr != nullptr) DestroyCursor (ptr); }\r
+        };\r
+\r
+        using CursorPtr = std::unique_ptr<std::remove_pointer_t<HCURSOR>, CursorDestructor>;\r
+\r
         const CustomMouseCursorInfo info;\r
-        std::map<int, HCURSOR> cursorsBySize;\r
+        std::map<int, CursorPtr> cursorsBySize;\r
     };\r
 \r
     static auto getCursorSizeForPeerFunction() -> int (*) (ComponentPeer&)\r
diff --git a/modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h b/modules/juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h
new file mode 100644 (file)
index 0000000..82b9038
--- /dev/null
@@ -0,0 +1,118 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
+   Agreement and JUCE Privacy Policy.\r
+\r
+   End User License Agreement: www.juce.com/juce-7-licence\r
+   Privacy Policy: www.juce.com/juce-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+extern XContext windowHandleXContext;\r
+\r
+/*  Attaches a pointer to a given window, so that it can be retrieved with XFindContext on\r
+    the windowHandleXContext.\r
+*/\r
+class ScopedWindowAssociation\r
+{\r
+public:\r
+    ScopedWindowAssociation() = default;\r
+\r
+    ScopedWindowAssociation (void* associatedIn, Window windowIn)\r
+        : associatedPointer ([&]() -> void*\r
+          {\r
+              if (associatedIn == nullptr)\r
+                  return nullptr;\r
+\r
+              // If you hit this, there's already a pointer associated with this window.\r
+              const auto display = XWindowSystem::getInstance()->getDisplay();\r
+              jassert (! getAssociatedPointer (display, windowIn).has_value());\r
+\r
+              if (X11Symbols::getInstance()->xSaveContext (display,\r
+                                                           static_cast<XID> (windowIn),\r
+                                                           windowHandleXContext,\r
+                                                           unalignedPointerCast<XPointer> (associatedIn)) != 0)\r
+              {\r
+                  jassertfalse;\r
+                  return nullptr;\r
+              }\r
+\r
+              return associatedIn;\r
+          }()),\r
+          window (static_cast<XID> (windowIn)) {}\r
+\r
+    ScopedWindowAssociation (const ScopedWindowAssociation&) = delete;\r
+    ScopedWindowAssociation& operator= (const ScopedWindowAssociation&) = delete;\r
+\r
+    ScopedWindowAssociation (ScopedWindowAssociation&& other) noexcept\r
+        : associatedPointer (std::exchange (other.associatedPointer, nullptr)), window (other.window) {}\r
+\r
+    ScopedWindowAssociation& operator= (ScopedWindowAssociation&& other) noexcept\r
+    {\r
+        ScopedWindowAssociation { std::move (other) }.swap (*this);\r
+        return *this;\r
+    }\r
+\r
+    ~ScopedWindowAssociation() noexcept\r
+    {\r
+        if (associatedPointer == nullptr)\r
+            return;\r
+\r
+        const auto display = XWindowSystem::getInstance()->getDisplay();\r
+        const auto ptr = getAssociatedPointer (display, window);\r
+\r
+        if (! ptr.has_value())\r
+        {\r
+            // If you hit this, something else has cleared this association before we were able to.\r
+            jassertfalse;\r
+            return;\r
+        }\r
+\r
+        jassert (unalignedPointerCast<XPointer> (associatedPointer) == *ptr);\r
+\r
+        if (X11Symbols::getInstance()->xDeleteContext (display, window, windowHandleXContext) != 0)\r
+            jassertfalse;\r
+    }\r
+\r
+    bool isValid() const { return associatedPointer != nullptr; }\r
+\r
+private:\r
+    static std::optional<XPointer> getAssociatedPointer (Display* display, Window window)\r
+    {\r
+        XPointer ptr{};\r
+\r
+        if (X11Symbols::getInstance()->xFindContext (display, window, windowHandleXContext, &ptr) != 0)\r
+            return std::nullopt;\r
+\r
+        return ptr;\r
+    }\r
+\r
+    void swap (ScopedWindowAssociation& other) noexcept\r
+    {\r
+        std::swap (other.associatedPointer, associatedPointer);\r
+        std::swap (other.window, window);\r
+    }\r
+\r
+    void* associatedPointer = nullptr;\r
+    XID window{};\r
+};\r
+\r
+} // namespace juce\r
index da1a27308e691545b929aa9278bdb90470918374..6103b7449736ec2a162d163cf212944e2d316fa8 100644 (file)
@@ -361,10 +361,8 @@ namespace X11ErrorHandling
         return 0;\r
     }\r
 \r
-    static int errorHandler (::Display* display, XErrorEvent* event)\r
+    static int errorHandler ([[maybe_unused]] ::Display* display, [[maybe_unused]] XErrorEvent* event)\r
     {\r
-        ignoreUnused (display, event);\r
-\r
        #if JUCE_DEBUG_XERRORS\r
         char errorStr[64]   = { 0 };\r
         char requestStr[64] = { 0 };\r
@@ -1434,15 +1432,21 @@ ComponentPeer* getPeerFor (::Window windowH)
     if (windowH == 0)\r
         return nullptr;\r
 \r
-    XPointer peer = nullptr;\r
-\r
     if (auto* display = XWindowSystem::getInstance()->getDisplay())\r
     {\r
         XWindowSystemUtilities::ScopedXLock xLock;\r
-        X11Symbols::getInstance()->xFindContext (display, (XID) windowH, windowHandleXContext, &peer);\r
+\r
+        if (XPointer peer = nullptr;\r
+            X11Symbols::getInstance()->xFindContext (display,\r
+                                                     static_cast<XID> (windowH),\r
+                                                     windowHandleXContext,\r
+                                                     &peer) == 0)\r
+        {\r
+            return unalignedPointerCast<ComponentPeer*> (peer);\r
+        }\r
     }\r
 \r
-    return unalignedPointerCast<ComponentPeer*> (peer);\r
+    return nullptr;\r
 }\r
 \r
 //==============================================================================\r
@@ -1545,7 +1549,7 @@ static int getAllEventsMask (bool ignoresMouseClicks)
                                                              &swa);\r
 \r
     // Set the window context to identify the window handle object\r
-    if (X11Symbols::getInstance()->xSaveContext (display, (XID) windowH, windowHandleXContext, (XPointer) peer))\r
+    if (! peer->setWindowAssociation (windowH))\r
     {\r
         // Failed\r
         jassertfalse;\r
@@ -1627,10 +1631,7 @@ void XWindowSystem::destroyWindow (::Window windowH)
 \r
     XWindowSystemUtilities::ScopedXLock xLock;\r
 \r
-    XPointer handlePointer;\r
-\r
-    if (! X11Symbols::getInstance()->xFindContext (display, (XID) windowH, windowHandleXContext, &handlePointer))\r
-        X11Symbols::getInstance()->xDeleteContext (display, (XID) windowH, windowHandleXContext);\r
+    peer->clearWindowAssociation();\r
 \r
     X11Symbols::getInstance()->xDestroyWindow (display, windowH);\r
 \r
@@ -2565,6 +2566,22 @@ Array<Displays::Display> XWindowSystem::findDisplays (float masterScale) const
                                         d.isMain = (mainDisplay == screens->outputs[j]) && (i == 0);\r
                                         d.dpi = DisplayHelpers::getDisplayDPI (display, 0);\r
 \r
+                                        d.verticalFrequencyHz = [&]() -> std::optional<double>\r
+                                        {\r
+                                            if (crtc->mode != None)\r
+                                            {\r
+                                                if (auto it = std::find_if (screens->modes,\r
+                                                                            screens->modes + screens->nmode,\r
+                                                                            [&crtc] (const auto& m) { return m.id == crtc->mode; });\r
+                                                    it != screens->modes + screens->nmode)\r
+                                                {\r
+                                                    return (double) it->dotClock / ((double) it->hTotal * (double) it->vTotal);\r
+                                                }\r
+                                            }\r
+\r
+                                            return {};\r
+                                        }();\r
+\r
                                         // The raspberry pi returns a zero sized display, so we need to guard for divide-by-zero\r
                                         if (output->mm_width > 0 && output->mm_height > 0)\r
                                             d.dpi = ((static_cast<double> (crtc->width)  * 25.4 * 0.5) / static_cast<double> (output->mm_width))\r
@@ -2666,7 +2683,7 @@ Array<Displays::Display> XWindowSystem::findDisplays (float masterScale) const
     return displays;\r
 }\r
 \r
-::Window XWindowSystem::createKeyProxy (::Window windowH) const\r
+::Window XWindowSystem::createKeyProxy (::Window windowH)\r
 {\r
     jassert (windowH != 0);\r
 \r
@@ -2680,7 +2697,6 @@ Array<Displays::Display> XWindowSystem::findDisplays (float masterScale) const
                                                               &swa);\r
 \r
     X11Symbols::getInstance()->xMapWindow (display, keyProxy);\r
-    X11Symbols::getInstance()->xSaveContext (display, (XID) keyProxy, windowHandleXContext, (XPointer) this);\r
 \r
     return keyProxy;\r
 }\r
@@ -2689,11 +2705,6 @@ void XWindowSystem::deleteKeyProxy (::Window keyProxy) const
 {\r
     jassert (keyProxy != 0);\r
 \r
-    XPointer handlePointer;\r
-\r
-    if (! X11Symbols::getInstance()->xFindContext (display, (XID) keyProxy, windowHandleXContext, &handlePointer))\r
-          X11Symbols::getInstance()->xDeleteContext (display, (XID) keyProxy, windowHandleXContext);\r
-\r
     X11Symbols::getInstance()->xDestroyWindow (display, keyProxy);\r
     X11Symbols::getInstance()->xSync (display, false);\r
 \r
@@ -3129,6 +3140,12 @@ XWindowSystem::VisualAndDepth XWindowSystem::DisplayVisuals::getBestVisualForWin
     if (visual24Bit != nullptr)\r
         return { visual24Bit, 24 };\r
 \r
+    if (visual32Bit != nullptr)\r
+        return { visual32Bit, 32 };\r
+\r
+    // No visual available!\r
+    jassert (visual16Bit != nullptr);\r
+\r
     return { visual16Bit, 16 };\r
 }\r
 \r
index 0659adbeccbcab35969074fd39e54d6caf8dcbbc..7fd30a847388fb74376f847d18e7825f42a3bcda 100644 (file)
@@ -225,7 +225,7 @@ public:
 \r
     Array<Displays::Display> findDisplays (float masterScale) const;\r
 \r
-    ::Window createKeyProxy (::Window) const;\r
+    ::Window createKeyProxy (::Window);\r
     void deleteKeyProxy (::Window) const;\r
 \r
     bool externalDragFileInit (LinuxComponentPeer*, const StringArray& files, bool canMove, std::function<void()>&& callback) const;\r
index e0ff54a418fb57cc336c9107ec7d745814125db7..b6f265458600bd0794209aa69bee7d71564bf337 100644 (file)
@@ -630,6 +630,9 @@ void ComboBox::handleAsyncUpdate()
     if (onChange != nullptr)\r
         onChange();\r
 \r
+    if (checker.shouldBailOut())\r
+        return;\r
+\r
     if (auto* handler = getAccessibilityHandler())\r
         handler->notifyAccessibilityEvent (AccessibilityEvent::valueChanged);\r
 }\r
index f58f2f81ae0e67eb159a5c848e1cf9334fe48cd4..43700aa34b8a0ef1eed83c665375a1a141709bb6 100644 (file)
@@ -525,7 +525,7 @@ ListBox::ListBox (const String& name, ListBoxModel* const m)
     setFocusContainerType (FocusContainerType::focusContainer);\r
     colourChanged();\r
 \r
-    setModel (m);\r
+    assignModelPtr (m);\r
 }\r
 \r
 ListBox::~ListBox()\r
@@ -1207,9 +1207,8 @@ std::unique_ptr<AccessibilityHandler> ListBox::createAccessibilityHandler()
 }\r
 \r
 //==============================================================================\r
-Component* ListBoxModel::refreshComponentForRow (int, bool, Component* existingComponentToUpdate)\r
+Component* ListBoxModel::refreshComponentForRow (int, bool, [[maybe_unused]] Component* existingComponentToUpdate)\r
 {\r
-    ignoreUnused (existingComponentToUpdate);\r
     jassert (existingComponentToUpdate == nullptr); // indicates a failure in the code that recycles the components\r
     return nullptr;\r
 }\r
index d1182ec9231d5c45708a5cf88749530a60a62314..58e593182dc287a76c8e12fc15310457a3ee873b 100644 (file)
@@ -221,7 +221,6 @@ public:
 \r
             updateText();\r
             owner.repaint();\r
-            updatePopupDisplay (newValue);\r
 \r
             triggerChangeMessage (notification);\r
         }\r
@@ -255,7 +254,7 @@ public:
             lastValueMin = newValue;\r
             valueMin = newValue;\r
             owner.repaint();\r
-            updatePopupDisplay (newValue);\r
+            updatePopupDisplay();\r
 \r
             triggerChangeMessage (notification);\r
         }\r
@@ -289,7 +288,7 @@ public:
             lastValueMax = newValue;\r
             valueMax = newValue;\r
             owner.repaint();\r
-            updatePopupDisplay (valueMax.getValue());\r
+            updatePopupDisplay();\r
 \r
             triggerChangeMessage (notification);\r
         }\r
@@ -363,6 +362,9 @@ public:
         if (owner.onValueChange != nullptr)\r
             owner.onValueChange();\r
 \r
+        if (checker.shouldBailOut())\r
+            return;\r
+\r
         if (auto* handler = owner.getAccessibilityHandler())\r
             handler->notifyAccessibilityEvent (AccessibilityEvent::valueChanged);\r
     }\r
@@ -453,6 +455,8 @@ public:
             if (newValue != valueBox->getText())\r
                 valueBox->setText (newValue, dontSendNotification);\r
         }\r
+\r
+        updatePopupDisplay();\r
     }\r
 \r
     double constrainedValue (double value) const\r
@@ -1061,25 +1065,36 @@ public:
                                             | ComponentPeer::windowIgnoresKeyPresses\r
                                             | ComponentPeer::windowIgnoresMouseClicks);\r
 \r
-            if (style == SliderStyle::TwoValueHorizontal\r
-                || style == SliderStyle::TwoValueVertical)\r
-            {\r
-                updatePopupDisplay (sliderBeingDragged == 2 ? getMaxValue()\r
-                                                            : getMinValue());\r
-            }\r
-            else\r
-            {\r
-                updatePopupDisplay (getValue());\r
-            }\r
-\r
+            updatePopupDisplay();\r
             popupDisplay->setVisible (true);\r
         }\r
     }\r
 \r
-    void updatePopupDisplay (double valueToShow)\r
+    void updatePopupDisplay()\r
     {\r
-        if (popupDisplay != nullptr)\r
-            popupDisplay->updatePosition (owner.getTextFromValue (valueToShow));\r
+        if (popupDisplay == nullptr)\r
+            return;\r
+\r
+        const auto valueToShow = [this]\r
+        {\r
+            constexpr SliderStyle multiSliderStyles[] { SliderStyle::TwoValueHorizontal,\r
+                                                        SliderStyle::TwoValueVertical,\r
+                                                        SliderStyle::ThreeValueHorizontal,\r
+                                                        SliderStyle::ThreeValueVertical };\r
+\r
+            if (std::find (std::begin (multiSliderStyles), std::end (multiSliderStyles), style) == std::end (multiSliderStyles))\r
+                return getValue();\r
+\r
+            if (sliderBeingDragged == 2)\r
+                return getMaxValue();\r
+\r
+            if (sliderBeingDragged == 1)\r
+                return getMinValue();\r
+\r
+            return getValue();\r
+        }();\r
+\r
+        popupDisplay->updatePosition (owner.getTextFromValue (valueToShow));\r
     }\r
 \r
     bool canDoubleClickToValue() const\r
index 4dc53dc32c4be453e9b1a5a76384a3fc2641a9ba..11075ace7ee70495e087dfecee30a2933fe2f406 100644 (file)
@@ -500,6 +500,33 @@ void TableHeaderComponent::reactToMenuItem (const int menuReturnId, const int /*
         setColumnVisible (menuReturnId, ! isColumnVisible (menuReturnId));\r
 }\r
 \r
+void TableHeaderComponent::drawColumnHeader (Graphics& g, LookAndFeel& lf, const ColumnInfo& ci)\r
+{\r
+    // Only paint columns that are visible\r
+    if (! ci.isVisible())\r
+        return;\r
+\r
+    // If this column is being dragged, it shouldn't be drawn in the table header\r
+    if (ci.id == columnIdBeingDragged && dragOverlayComp != nullptr && dragOverlayComp->isVisible())\r
+        return;\r
+\r
+    // There's no point drawing this column header if no part of it is visible\r
+    if (! g.getClipBounds()\r
+           .getHorizontalRange()\r
+           .intersects (Range<int>::withStartAndLength (ci.getX(), ci.width)))\r
+        return;\r
+\r
+    Graphics::ScopedSaveState ss (g);\r
+\r
+    g.setOrigin (ci.getX(), ci.getY());\r
+    g.reduceClipRegion (0, 0, ci.width, ci.getHeight());\r
+\r
+    lf.drawTableHeaderColumn (g, *this, ci.getTitle(), ci.id, ci.width, getHeight(),\r
+                              ci.id == columnIdUnderMouse,\r
+                              ci.id == columnIdUnderMouse && isMouseButtonDown(),\r
+                              ci.propertyFlags);\r
+}\r
+\r
 void TableHeaderComponent::paint (Graphics& g)\r
 {\r
     auto& lf = getLookAndFeel();\r
@@ -507,48 +534,18 @@ void TableHeaderComponent::paint (Graphics& g)
     lf.drawTableHeaderBackground (g, *this);\r
 \r
     for (auto* ci : columns)\r
-    {\r
-        if (ci->isVisible() && ci->getWidth() > 0)\r
-        {\r
-            Graphics::ScopedSaveState ss (g);\r
-\r
-            g.setOrigin (ci->getX(), ci->getY());\r
-            g.reduceClipRegion (0, 0, ci->getWidth(), ci->getHeight());\r
-\r
-            lf.drawTableHeaderColumn (g, *this, ci->getTitle(), ci->id, ci->width, getHeight(),\r
-                                      ci->id == columnIdUnderMouse,\r
-                                      ci->id == columnIdUnderMouse && isMouseButtonDown(),\r
-                                      ci->propertyFlags);\r
-        }\r
-    }\r
+        drawColumnHeader (g, lf, *ci);\r
 }\r
 \r
 void TableHeaderComponent::resized()\r
 {\r
-    auto clip = getBounds();\r
-\r
     int x = 0;\r
 \r
-    for (auto* ci : columns)\r
-        ci->setBounds (0, 0, 0, 0);\r
-\r
     for (auto* ci : columns)\r
     {\r
-        if (ci->isVisible())\r
-        {\r
-            if (x + ci->width > clip.getX()\r
-                && (ci->id != columnIdBeingDragged\r
-                    || dragOverlayComp == nullptr\r
-                    || ! dragOverlayComp->isVisible()))\r
-            {\r
-                ci->setBounds (x, 0, ci->width, getHeight());\r
-            }\r
-\r
-            x += ci->width;\r
-\r
-            if (x >= clip.getRight())\r
-                break;\r
-        }\r
+        const auto widthToUse = ci->isVisible() ? ci->width : 0;\r
+        ci->setBounds (x, 0, widthToUse, getHeight());\r
+        x += widthToUse;\r
     }\r
 }\r
 \r
index 3d1b017350206cc4abcdfb804cf7ec513a69d842..5afa5a3854cba4eb114f561325ed71311bb5a48a 100644 (file)
@@ -453,6 +453,7 @@ private:
     void updateColumnUnderMouse (const MouseEvent&);\r
     void setColumnUnderMouse (int columnId);\r
     void resizeColumnsToFit (int firstColumnIndex, int targetTotalWidth);\r
+    void drawColumnHeader (Graphics&, LookAndFeel&, const ColumnInfo&);\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TableHeaderComponent)\r
 };\r
index b332e5dc06098943559d7b2b4af2ee5c67016dc9..00cd8c79a73bdbf552904ada83fb3daa2e085304 100644 (file)
@@ -725,9 +725,8 @@ void TableListBoxModel::listWasScrolled()                               {}
 String TableListBoxModel::getCellTooltip (int /*rowNumber*/, int /*columnId*/)    { return {}; }\r
 var TableListBoxModel::getDragSourceDescription (const SparseSet<int>&)           { return {}; }\r
 \r
-Component* TableListBoxModel::refreshComponentForCell (int, int, bool, Component* existingComponentToUpdate)\r
+Component* TableListBoxModel::refreshComponentForCell (int, int, bool, [[maybe_unused]] Component* existingComponentToUpdate)\r
 {\r
-    ignoreUnused (existingComponentToUpdate);\r
     jassert (existingComponentToUpdate == nullptr); // indicates a failure in the code that recycles the components\r
     return nullptr;\r
 }\r
index 10a09d3a64e1d3e91ff8e5728bccb889704bdf94..79be3ecca2bb0bea61660b95893c0faf854a0e2d 100644 (file)
@@ -944,13 +944,14 @@ TextEditor::TextEditor (const String& name, juce_wchar passwordChar)
 \r
     setWantsKeyboardFocus (true);\r
     recreateCaret();\r
-\r
-    juce::Desktop::getInstance().addGlobalMouseListener (this);\r
 }\r
 \r
 TextEditor::~TextEditor()\r
 {\r
-    juce::Desktop::getInstance().removeGlobalMouseListener (this);\r
+    giveAwayKeyboardFocus();\r
+\r
+    if (auto* peer = getPeer())\r
+        peer->refreshTextInputTarget();\r
 \r
     textValue.removeListener (textHolder);\r
     textValue.referTo (Value());\r
@@ -1046,7 +1047,7 @@ bool TextEditor::isReadOnly() const noexcept
 \r
 bool TextEditor::isTextInputActive() const\r
 {\r
-    return ! isReadOnly() && (! clicksOutsideDismissVirtualKeyboard || mouseDownInEditor);\r
+    return ! isReadOnly() && (! clicksOutsideDismissVirtualKeyboard || globalMouseListener.lastMouseDownInEditor());\r
 }\r
 \r
 void TextEditor::setReturnKeyStartsNewLine (bool shouldStartNewLine)\r
@@ -1244,7 +1245,7 @@ void TextEditor::setText (const String& newText, bool sendTextChangeMessage)
         textValue = newText;\r
 \r
         auto oldCursorPos = caretPosition;\r
-        bool cursorWasAtEnd = oldCursorPos >= getTotalNumChars();\r
+        auto cursorWasAtEnd = oldCursorPos >= getTotalNumChars();\r
 \r
         clearInternal (nullptr);\r
         insert (newText, 0, currentFont, findColour (textColourId), nullptr, caretPosition);\r
@@ -1380,26 +1381,23 @@ void TextEditor::repaintText (Range<int> range)
 }\r
 \r
 //==============================================================================\r
-void TextEditor::moveCaret (int newCaretPos)\r
+void TextEditor::moveCaret (const int newCaretPos)\r
 {\r
-    if (newCaretPos < 0)\r
-        newCaretPos = 0;\r
-    else\r
-        newCaretPos = jmin (newCaretPos, getTotalNumChars());\r
+    const auto clamped = std::clamp (newCaretPos, 0, getTotalNumChars());\r
 \r
-    if (newCaretPos != getCaretPosition())\r
-    {\r
-        caretPosition = newCaretPos;\r
+    if (clamped == getCaretPosition())\r
+        return;\r
 \r
-        if (hasKeyboardFocus (false))\r
-            textHolder->restartTimer();\r
+    caretPosition = clamped;\r
 \r
-        scrollToMakeSureCursorIsVisible();\r
-        updateCaretPosition();\r
+    if (hasKeyboardFocus (false))\r
+        textHolder->restartTimer();\r
 \r
-        if (auto* handler = getAccessibilityHandler())\r
-            handler->notifyAccessibilityEvent (AccessibilityEvent::textChanged);\r
-    }\r
+    scrollToMakeSureCursorIsVisible();\r
+    updateCaretPosition();\r
+\r
+    if (auto* handler = getAccessibilityHandler())\r
+        handler->notifyAccessibilityEvent (AccessibilityEvent::textChanged);\r
 }\r
 \r
 int TextEditor::getCaretPosition() const\r
@@ -1654,15 +1652,11 @@ int TextEditor::getCharIndexForPoint (const Point<int> point) const
 \r
 void TextEditor::insertTextAtCaret (const String& t)\r
 {\r
-    String newText (inputFilter != nullptr ? inputFilter->filterNewText (*this, t) : t);\r
-\r
-    if (isMultiLine())\r
-        newText = newText.replace ("\r\n", "\n");\r
-    else\r
-        newText = newText.replaceCharacters ("\r\n", "  ");\r
-\r
-    const int insertIndex = selection.getStart();\r
-    const int newCaretPos = insertIndex + newText.length();\r
+    const auto filtered = inputFilter != nullptr ? inputFilter->filterNewText (*this, t) : t;\r
+    const auto newText = isMultiLine() ? filtered.replace ("\r\n", "\n")\r
+                                       : filtered.replaceCharacters ("\r\n", "  ");\r
+    const auto insertIndex = selection.getStart();\r
+    const auto newCaretPos = insertIndex + newText.length();\r
 \r
     remove (selection, getUndoManager(),\r
             newText.isNotEmpty() ? newCaretPos - 1 : newCaretPos);\r
@@ -1851,11 +1845,6 @@ void TextEditor::performPopupMenuAction (const int menuItemID)
 //==============================================================================\r
 void TextEditor::mouseDown (const MouseEvent& e)\r
 {\r
-    mouseDownInEditor = e.originalComponent == this;\r
-\r
-    if (! mouseDownInEditor)\r
-        return;\r
-\r
     beginDragAutoRepeat (100);\r
     newTransaction();\r
 \r
@@ -1893,9 +1882,6 @@ void TextEditor::mouseDown (const MouseEvent& e)
 \r
 void TextEditor::mouseDrag (const MouseEvent& e)\r
 {\r
-    if (! mouseDownInEditor)\r
-        return;\r
-\r
     if (wasFocused || ! selectAllTextWhenFocused)\r
         if (! (popupMenuEnabled && e.mods.isPopupMenu()))\r
             moveCaretTo (getTextIndexAt (e.getPosition()), true);\r
@@ -1903,9 +1889,6 @@ void TextEditor::mouseDrag (const MouseEvent& e)
 \r
 void TextEditor::mouseUp (const MouseEvent& e)\r
 {\r
-    if (! mouseDownInEditor)\r
-        return;\r
-\r
     newTransaction();\r
     textHolder->restartTimer();\r
 \r
@@ -1918,9 +1901,6 @@ void TextEditor::mouseUp (const MouseEvent& e)
 \r
 void TextEditor::mouseDoubleClick (const MouseEvent& e)\r
 {\r
-    if (! mouseDownInEditor)\r
-        return;\r
-\r
     int tokenEnd = getTextIndexAt (e.getPosition());\r
     int tokenStart = 0;\r
 \r
@@ -1987,9 +1967,6 @@ void TextEditor::mouseDoubleClick (const MouseEvent& e)
 \r
 void TextEditor::mouseWheelMove (const MouseEvent& e, const MouseWheelDetails& wheel)\r
 {\r
-    if (! mouseDownInEditor)\r
-        return;\r
-\r
     if (! viewport->useMouseWheelMoveIfNeeded (e, wheel))\r
         Component::mouseWheelMove (e, wheel);\r
 }\r
@@ -2036,7 +2013,13 @@ bool TextEditor::moveCaretUp (bool selecting)
         return moveCaretToStartOfLine (selecting);\r
 \r
     const auto caretPos = (getCaretRectangle() - getTextOffset()).toFloat();\r
-    return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), caretPos.getY() - 1.0f), selecting);\r
+\r
+    const auto newY = caretPos.getY() - 1.0f;\r
+\r
+    if (newY < 0.0f)\r
+        return moveCaretToStartOfLine (selecting);\r
+\r
+    return moveCaretWithTransaction (indexAtPosition (caretPos.getX(), newY), selecting);\r
 }\r
 \r
 bool TextEditor::moveCaretDown (bool selecting)\r
@@ -2283,24 +2266,24 @@ void TextEditor::handleCommandMessage (const int commandId)
     case TextEditorDefs::textChangeMessageId:\r
         listeners.callChecked (checker, [this] (Listener& l) { l.textEditorTextChanged (*this); });\r
 \r
-        if (! checker.shouldBailOut() && onTextChange != nullptr)\r
-            onTextChange();\r
+        if (! checker.shouldBailOut())\r
+            NullCheckedInvocation::invoke (onTextChange);\r
 \r
         break;\r
 \r
     case TextEditorDefs::returnKeyMessageId:\r
         listeners.callChecked (checker, [this] (Listener& l) { l.textEditorReturnKeyPressed (*this); });\r
 \r
-        if (! checker.shouldBailOut() && onReturnKey != nullptr)\r
-            onReturnKey();\r
+        if (! checker.shouldBailOut())\r
+            NullCheckedInvocation::invoke (onReturnKey);\r
 \r
         break;\r
 \r
     case TextEditorDefs::escapeKeyMessageId:\r
         listeners.callChecked (checker, [this] (Listener& l) { l.textEditorEscapeKeyPressed (*this); });\r
 \r
-        if (! checker.shouldBailOut() && onEscapeKey != nullptr)\r
-            onEscapeKey();\r
+        if (! checker.shouldBailOut())\r
+            NullCheckedInvocation::invoke (onEscapeKey);\r
 \r
         break;\r
 \r
@@ -2308,8 +2291,8 @@ void TextEditor::handleCommandMessage (const int commandId)
         updateValueFromText();\r
         listeners.callChecked (checker, [this] (Listener& l) { l.textEditorFocusLost (*this); });\r
 \r
-        if (! checker.shouldBailOut() && onFocusLost != nullptr)\r
-            onFocusLost();\r
+        if (! checker.shouldBailOut())\r
+            NullCheckedInvocation::invoke (onFocusLost);\r
 \r
         break;\r
 \r
@@ -2325,6 +2308,11 @@ void TextEditor::setTemporaryUnderlining (const Array<Range<int>>& newUnderlined
     repaint();\r
 }\r
 \r
+TextInputTarget::VirtualKeyboardType TextEditor::getKeyboardType()\r
+{\r
+    return passwordCharacter != 0 ? passwordKeyboard : keyboardType;\r
+}\r
+\r
 //==============================================================================\r
 UndoManager* TextEditor::getUndoManager() noexcept\r
 {\r
@@ -2614,9 +2602,9 @@ int TextEditor::indexAtPosition (const float x, const float y) const
     {\r
         for (Iterator i (*this); i.next();)\r
         {\r
-            if (y < i.lineY + i.lineHeight)\r
+            if (y < i.lineY + (i.lineHeight * lineSpacing))\r
             {\r
-                if (y < i.lineY)\r
+                if (jmax (0.0f, y) < i.lineY)\r
                     return jmax (0, i.indexInText - 1);\r
 \r
                 if (x <= i.atomX || i.atom->isNewLine())\r
index d93e6af1c7de32b5cc6460910667c942c3fb2956..748bdcf926ba85bdee1e1ef999fb0c23f9d2ce95 100644 (file)
@@ -742,7 +742,7 @@ public:
     /** @internal */\r
     void setTemporaryUnderlining (const Array<Range<int>>&) override;\r
     /** @internal */\r
-    VirtualKeyboardType getKeyboardType() override    { return keyboardType; }\r
+    VirtualKeyboardType getKeyboardType() override;\r
 \r
 protected:\r
     //==============================================================================\r
@@ -771,10 +771,26 @@ private:
     struct RemoveAction;\r
     class EditorAccessibilityHandler;\r
 \r
+    class GlobalMouseListener : private MouseListener\r
+    {\r
+    public:\r
+        explicit GlobalMouseListener (Component& e) : editor (e) { Desktop::getInstance().addGlobalMouseListener    (this); }\r
+        ~GlobalMouseListener() override                          { Desktop::getInstance().removeGlobalMouseListener (this); }\r
+\r
+        bool lastMouseDownInEditor() const { return mouseDownInEditor; }\r
+\r
+    private:\r
+        void mouseDown (const MouseEvent& event) override { mouseDownInEditor = event.originalComponent == &editor; }\r
+\r
+        Component& editor;\r
+        bool mouseDownInEditor = false;\r
+    };\r
+\r
     std::unique_ptr<Viewport> viewport;\r
     TextHolderComponent* textHolder;\r
     BorderSize<int> borderSize { 1, 1, 1, 3 };\r
     Justification justification { Justification::topLeft };\r
+    const GlobalMouseListener globalMouseListener { *this };\r
 \r
     bool readOnly = false;\r
     bool caretVisible = true;\r
@@ -791,7 +807,6 @@ private:
     bool valueTextNeedsUpdating = false;\r
     bool consumeEscAndReturnKeys = true;\r
     bool underlineWhitespace = true;\r
-    bool mouseDownInEditor = false;\r
     bool clicksOutsideDismissVirtualKeyboard = false;\r
 \r
     UndoManager undoManager;\r
index 38c2277740238bb169d78d1d3df75672d7262827..75d261787b14a73f6a7323732b59736fb69a5c29 100644 (file)
@@ -747,9 +747,10 @@ public:
 \r
     enum class Async { yes, no };\r
 \r
-    void recalculatePositions (Async useAsyncUpdate)\r
+    void recalculatePositions (Async useAsyncUpdate, std::optional<Point<int>> viewportPosition)\r
     {\r
         needsRecalculating = true;\r
+        viewportAfterRecalculation = std::move (viewportPosition);\r
 \r
         if (useAsyncUpdate == Async::yes)\r
             triggerAsyncUpdate();\r
@@ -765,15 +766,13 @@ private:
 \r
     void handleAsyncUpdate() override\r
     {\r
-        if (structureChanged)\r
+        if (std::exchange (structureChanged, false))\r
         {\r
             if (auto* handler = owner.getAccessibilityHandler())\r
                 handler->notifyAccessibilityEvent (AccessibilityEvent::structureChanged);\r
-\r
-            structureChanged = false;\r
         }\r
 \r
-        if (needsRecalculating)\r
+        if (std::exchange (needsRecalculating, false))\r
         {\r
             if (auto* root = owner.rootItem)\r
             {\r
@@ -790,7 +789,8 @@ private:
 \r
             updateComponents (false);\r
 \r
-            needsRecalculating = false;\r
+            if (const auto viewportPosition = std::exchange (viewportAfterRecalculation, {}))\r
+                setViewPosition (viewportPosition->getX(), viewportPosition->getY());\r
         }\r
     }\r
 \r
@@ -810,6 +810,7 @@ private:
     TreeView& owner;\r
     int lastX = -1;\r
     bool structureChanged = false, needsRecalculating = false;\r
+    std::optional<Point<int>> viewportAfterRecalculation;\r
 \r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (TreeViewport)\r
 };\r
@@ -858,7 +859,7 @@ void TreeView::setRootItem (TreeViewItem* const newRootItem)
             rootItem->setOpen (true);\r
         }\r
 \r
-        viewport->recalculatePositions (TreeViewport::Async::no);\r
+        viewport->recalculatePositions (TreeViewport::Async::no, {});\r
     }\r
 }\r
 \r
@@ -1020,10 +1021,6 @@ void TreeView::restoreOpennessState (const XmlElement& newState, bool restoreSto
     {\r
         rootItem->restoreOpennessState (newState);\r
 \r
-        if (newState.hasAttribute ("scrollPos"))\r
-            viewport->setViewPosition (viewport->getViewPositionX(),\r
-                                       newState.getIntAttribute ("scrollPos"));\r
-\r
         if (restoreStoredSelection)\r
         {\r
             clearSelectedItems();\r
@@ -1033,7 +1030,11 @@ void TreeView::restoreOpennessState (const XmlElement& newState, bool restoreSto
                     item->setSelected (true, false);\r
         }\r
 \r
-        updateVisibleItems();\r
+        const auto scrollPos = newState.hasAttribute ("scrollPos")\r
+                             ? std::make_optional<Point<int>> (viewport->getViewPositionX(), newState.getIntAttribute ("scrollPos"))\r
+                             : std::nullopt;\r
+\r
+        updateVisibleItems (std::move (scrollPos));\r
     }\r
 }\r
 \r
@@ -1216,9 +1217,9 @@ bool TreeView::keyPressed (const KeyPress& key)
     return false;\r
 }\r
 \r
-void TreeView::updateVisibleItems()\r
+void TreeView::updateVisibleItems (std::optional<Point<int>> viewportPosition)\r
 {\r
-    viewport->recalculatePositions (TreeViewport::Async::yes);\r
+    viewport->recalculatePositions (TreeViewport::Async::yes, std::move (viewportPosition));\r
 }\r
 \r
 //==============================================================================\r
index 0a40a90ff189f554a3998aec9a4188020cbd93b3..608b3542bb2abc95ed2a626dc41b241a7ea44733 100644 (file)
@@ -935,7 +935,7 @@ private:
 \r
     std::unique_ptr<AccessibilityHandler> createAccessibilityHandler() override;\r
     void itemsChanged() noexcept;\r
-    void updateVisibleItems();\r
+    void updateVisibleItems (std::optional<Point<int>> viewportPosition = {});\r
     void updateButtonUnderMouse (const MouseEvent&);\r
     void showDragHighlight (const InsertPoint&) noexcept;\r
     void hideDragHighlight() noexcept;\r
index 3ab01734a58f828a4794aab20416e22dfbe72692..fdb36953ba5789ca17badd1312d0e0c879bc15e6 100644 (file)
@@ -182,7 +182,6 @@ bool ComponentPeer::handleKeyPress (const int keyCode, const juce_wchar textChar
                                      textCharacter));\r
 }\r
 \r
-\r
 bool ComponentPeer::handleKeyPress (const KeyPress& keyInfo)\r
 {\r
     bool keyWasUsed = false;\r
@@ -587,8 +586,8 @@ void ComponentPeer::setRepresentedFile (const File&)
 }\r
 \r
 //==============================================================================\r
-int ComponentPeer::getCurrentRenderingEngine() const            { return 0; }\r
-void ComponentPeer::setCurrentRenderingEngine (int index)       { jassert (index == 0); ignoreUnused (index); }\r
+int ComponentPeer::getCurrentRenderingEngine() const                             { return 0; }\r
+void ComponentPeer::setCurrentRenderingEngine ([[maybe_unused]] int index)       { jassert (index == 0); }\r
 \r
 //==============================================================================\r
 std::function<ModifierKeys()> ComponentPeer::getNativeRealtimeModifiers = nullptr;\r
@@ -607,7 +606,7 @@ void ComponentPeer::forceDisplayUpdate()
     Desktop::getInstance().displays->refresh();\r
 }\r
 \r
-void ComponentPeer::globalFocusChanged (Component*)\r
+void ComponentPeer::globalFocusChanged ([[maybe_unused]] Component* comp)\r
 {\r
     refreshTextInputTarget();\r
 }\r
index 64084b9d8223e0b83b31a2e07d331a0b65eceab4..fd1c4d09e8c29b67b628297320115bac2954c70e 100644 (file)
@@ -473,6 +473,34 @@ public:
     /** Removes a scale factor listener. */\r
     void removeScaleFactorListener (ScaleFactorListener* listenerToRemove)    { scaleFactorListeners.remove (listenerToRemove);  }\r
 \r
+    //==============================================================================\r
+    /** Used to receive callbacks on every vertical blank event of the display that the peer\r
+        currently belongs to.\r
+\r
+        On Linux this is currently limited to receiving callbacks from a timer approximately at\r
+        display refresh rate.\r
+\r
+        This is a low-level facility used by the peer implementations. If you wish to synchronise\r
+        Component events with the display refresh, you should probably use the VBlankAttachment,\r
+        which automatically takes care of listening to the vblank events of the right peer.\r
+\r
+        @see VBlankAttachment\r
+    */\r
+    struct JUCE_API  VBlankListener\r
+    {\r
+        /** Destructor. */\r
+        virtual ~VBlankListener() = default;\r
+\r
+        /** Called on every vertical blank of the display to which the peer is associated. */\r
+        virtual void onVBlank() = 0;\r
+    };\r
+\r
+    /** Adds a VBlankListener. */\r
+    void addVBlankListener (VBlankListener* listenerToAdd)       { vBlankListeners.add (listenerToAdd); }\r
+\r
+    /** Removes a VBlankListener. */\r
+    void removeVBlankListener (VBlankListener* listenerToRemove) { vBlankListeners.remove (listenerToRemove); }\r
+\r
     //==============================================================================\r
     /** On Windows and Linux this will return the OS scaling factor currently being applied\r
         to the native window. This is used to convert between physical and logical pixels\r
@@ -524,6 +552,7 @@ protected:
     ComponentBoundsConstrainer* constrainer = nullptr;\r
     static std::function<ModifierKeys()> getNativeRealtimeModifiers;\r
     ListenerList<ScaleFactorListener> scaleFactorListeners;\r
+    ListenerList<VBlankListener> vBlankListeners;\r
     Style style = Style::automatic;\r
 \r
 private:\r
index 3a4dc59d81db88cb3aa5d79a7432400c648fe877..b8d70abb96d1bd02af722fbc969201caf84af674 100644 (file)
@@ -68,13 +68,13 @@ public:
 \r
     //==============================================================================\r
     /** Sets the type of icon that should be used for the dialog box. */\r
-    JUCE_NODISCARD MessageBoxOptions withIconType (MessageBoxIconType type) const          { return with (*this, &MessageBoxOptions::iconType, type); }\r
+    [[nodiscard]] MessageBoxOptions withIconType (MessageBoxIconType type) const          { return with (*this, &MessageBoxOptions::iconType, type); }\r
 \r
     /** Sets the title of the dialog box. */\r
-    JUCE_NODISCARD MessageBoxOptions withTitle (const String& boxTitle) const              { return with (*this, &MessageBoxOptions::title, boxTitle); }\r
+    [[nodiscard]] MessageBoxOptions withTitle (const String& boxTitle) const              { return with (*this, &MessageBoxOptions::title, boxTitle); }\r
 \r
     /** Sets the message that should be displayed in the dialog box. */\r
-    JUCE_NODISCARD MessageBoxOptions withMessage (const String& boxMessage) const          { return with (*this, &MessageBoxOptions::message, boxMessage); }\r
+    [[nodiscard]] MessageBoxOptions withMessage (const String& boxMessage) const          { return with (*this, &MessageBoxOptions::message, boxMessage); }\r
 \r
     /** If the string passed in is not empty, this will add a button to the\r
         dialog box with the specified text.\r
@@ -82,10 +82,10 @@ public:
         Generally up to 3 buttons are supported for dialog boxes, so adding any more\r
         than this may have no effect.\r
     */\r
-    JUCE_NODISCARD MessageBoxOptions withButton (const String& text) const                 { auto copy = *this; copy.buttons.add (text); return copy; }\r
+    [[nodiscard]] MessageBoxOptions withButton (const String& text) const                 { auto copy = *this; copy.buttons.add (text); return copy; }\r
 \r
     /** The component that the dialog box should be associated with. */\r
-    JUCE_NODISCARD MessageBoxOptions withAssociatedComponent (Component* component) const  { return with (*this, &MessageBoxOptions::associatedComponent, component); }\r
+    [[nodiscard]] MessageBoxOptions withAssociatedComponent (Component* component) const  { return with (*this, &MessageBoxOptions::associatedComponent, component); }\r
 \r
     //==============================================================================\r
     /** Returns the icon type of the dialog box.\r
index 4ec6b765f8f70d4632fdb7b323c97bd2b37584f8..2cd5ff42da444371f26ea4692c5abe6a79d57293 100644 (file)
@@ -56,11 +56,11 @@ ThreadWithProgressWindow::~ThreadWithProgressWindow()
     stopThread (timeOutMsWhenCancelling);\r
 }\r
 \r
-void ThreadWithProgressWindow::launchThread (int priority)\r
+void ThreadWithProgressWindow::launchThread (Priority threadPriority)\r
 {\r
     JUCE_ASSERT_MESSAGE_THREAD\r
 \r
-    startThread (priority);\r
+    startThread (threadPriority);\r
     startTimer (100);\r
 \r
     {\r
@@ -105,9 +105,9 @@ void ThreadWithProgressWindow::timerCallback()
 void ThreadWithProgressWindow::threadComplete (bool) {}\r
 \r
 #if JUCE_MODAL_LOOPS_PERMITTED\r
-bool ThreadWithProgressWindow::runThread (const int priority)\r
+bool ThreadWithProgressWindow::runThread (Priority threadPriority)\r
 {\r
-    launchThread (priority);\r
+    launchThread (threadPriority);\r
 \r
     while (isTimerRunning())\r
         MessageManager::getInstance()->runDispatchLoopUntil (5);\r
index 0e6c3c42e228f87336224d5d030f150dd45b23f3..87bf0ef4e8bd81c9e82e38d4d861677b7efb836a 100644 (file)
@@ -122,10 +122,10 @@ public:
         Before returning, the dialog box will be hidden.\r
 \r
         @param priority   the priority to use when starting the thread - see\r
-                          Thread::startThread() for values\r
+                          Thread::Priority for values\r
         @returns true if the thread finished normally; false if the user pressed cancel\r
     */\r
-    bool runThread (int priority = 5);\r
+    bool runThread (Priority priority = Priority::normal);\r
    #endif\r
 \r
     /** Starts the thread and returns.\r
@@ -135,9 +135,9 @@ public:
         hidden and the threadComplete() method will be called.\r
 \r
         @param priority   the priority to use when starting the thread - see\r
-                          Thread::startThread() for values\r
+                          Thread::Priority for values\r
     */\r
-    void launchThread (int priority = 5);\r
+    void launchThread (Priority priority = Priority::normal);\r
 \r
     /** The thread should call this periodically to update the position of the progress bar.\r
 \r
index a4f00bf8c276debb1582ce9481cab5b843e54568..106adb16dc21ff944f9bfaa39e07e139d43976d6 100644 (file)
@@ -300,14 +300,15 @@ void TopLevelWindow::centreAroundComponent (Component* c, const int width, const
     {\r
         const auto scale = getDesktopScaleFactor() / Desktop::getInstance().getGlobalScaleFactor();\r
 \r
-        auto targetCentre = c->localPointToGlobal (c->getLocalBounds().getCentre()) / scale;\r
-        auto parentArea = getLocalArea (nullptr, c->getParentMonitorArea());\r
-\r
-        if (auto* parent = getParentComponent())\r
+        const auto [targetCentre, parentArea] = [&]\r
         {\r
-            targetCentre = parent->getLocalPoint (nullptr, targetCentre);\r
-            parentArea   = parent->getLocalBounds();\r
-        }\r
+            const auto globalTargetCentre = c->localPointToGlobal (c->getLocalBounds().getCentre()) / scale;\r
+\r
+            if (auto* parent = getParentComponent())\r
+                return std::make_pair (parent->getLocalPoint (nullptr, globalTargetCentre), parent->getLocalBounds());\r
+\r
+            return std::make_pair (globalTargetCentre, c->getParentMonitorArea() / scale);\r
+        }();\r
 \r
         setBounds (Rectangle<int> (targetCentre.x - width / 2,\r
                                    targetCentre.y - height / 2,\r
diff --git a/modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp b/modules/juce_gui_basics/windows/juce_VBlankAttachement.cpp
new file mode 100644 (file)
index 0000000..1b9be3b
--- /dev/null
@@ -0,0 +1,113 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
+   Agreement and JUCE Privacy Policy.\r
+\r
+   End User License Agreement: www.juce.com/juce-7-licence\r
+   Privacy Policy: www.juce.com/juce-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+VBlankAttachment::VBlankAttachment (Component* c, std::function<void()> callbackIn)\r
+    : owner (c),\r
+      callback (std::move (callbackIn))\r
+{\r
+    jassert (owner != nullptr && callback);\r
+\r
+    updateOwner();\r
+    updatePeer();\r
+}\r
+\r
+VBlankAttachment::VBlankAttachment (VBlankAttachment&& other)\r
+    : VBlankAttachment (other.owner, std::move (other.callback))\r
+{\r
+    other.cleanup();\r
+}\r
+\r
+VBlankAttachment& VBlankAttachment::operator= (VBlankAttachment&& other)\r
+{\r
+    cleanup();\r
+\r
+    owner = other.owner;\r
+    callback = std::move (other.callback);\r
+    updateOwner();\r
+    updatePeer();\r
+\r
+    other.cleanup();\r
+\r
+    return *this;\r
+}\r
+\r
+VBlankAttachment::~VBlankAttachment()\r
+{\r
+    cleanup();\r
+}\r
+\r
+void VBlankAttachment::onVBlank()\r
+{\r
+    callback();\r
+}\r
+\r
+void VBlankAttachment::componentParentHierarchyChanged (Component&)\r
+{\r
+    updatePeer();\r
+}\r
+\r
+void VBlankAttachment::updateOwner()\r
+{\r
+    if (auto previousLastOwner = std::exchange (lastOwner, owner); previousLastOwner != owner)\r
+    {\r
+        if (previousLastOwner != nullptr)\r
+            previousLastOwner->removeComponentListener (this);\r
+\r
+        if (owner != nullptr)\r
+            owner->addComponentListener (this);\r
+    }\r
+}\r
+\r
+void VBlankAttachment::updatePeer()\r
+{\r
+    if (owner != nullptr)\r
+    {\r
+        if (auto* peer = owner->getPeer())\r
+        {\r
+            peer->addVBlankListener (this);\r
+\r
+            if (lastPeer != peer && ComponentPeer::isValidPeer (lastPeer))\r
+                lastPeer->removeVBlankListener (this);\r
+\r
+            lastPeer = peer;\r
+        }\r
+    }\r
+    else if (auto peer = std::exchange (lastPeer, nullptr); ComponentPeer::isValidPeer (peer))\r
+    {\r
+        peer->removeVBlankListener (this);\r
+    }\r
+}\r
+\r
+void VBlankAttachment::cleanup()\r
+{\r
+    owner = nullptr;\r
+    updateOwner();\r
+    updatePeer();\r
+}\r
+\r
+} // namespace juce\r
diff --git a/modules/juce_gui_basics/windows/juce_VBlankAttachement.h b/modules/juce_gui_basics/windows/juce_VBlankAttachement.h
new file mode 100644 (file)
index 0000000..2eb9daa
--- /dev/null
@@ -0,0 +1,73 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
+   Agreement and JUCE Privacy Policy.\r
+\r
+   End User License Agreement: www.juce.com/juce-7-licence\r
+   Privacy Policy: www.juce.com/juce-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+/** Helper class to synchronise Component updates to the vertical blank event of the display that\r
+    the Component is presented on. This is useful when animating the Component's contents.\r
+*/\r
+class JUCE_API  VBlankAttachment final  : public ComponentPeer::VBlankListener,\r
+                                          public ComponentListener\r
+{\r
+public:\r
+    /** Default constructor for creating an empty object. */\r
+    VBlankAttachment() {}\r
+\r
+    /** Constructor. Creates an attachment that will call the passed in function at every vertical\r
+        blank event of the display that the passed in Component is currently visible on.\r
+\r
+        The Component must be valid for the entire lifetime of the VBlankAttachment.\r
+    */\r
+    VBlankAttachment (Component* c, std::function<void()> callbackIn);\r
+    VBlankAttachment (VBlankAttachment&& other);\r
+    VBlankAttachment& operator= (VBlankAttachment&& other);\r
+\r
+    /** Destructor. */\r
+    ~VBlankAttachment() override;\r
+\r
+    /** Returns true for a default constructed object. */\r
+    bool isEmpty() { return owner == nullptr; }\r
+\r
+    //==============================================================================\r
+    void onVBlank() override;\r
+\r
+    //==============================================================================\r
+    void componentParentHierarchyChanged (Component&) override;\r
+\r
+private:\r
+    void updateOwner();\r
+    void updatePeer();\r
+    void cleanup();\r
+\r
+    Component* owner = nullptr;\r
+    Component* lastOwner = nullptr;\r
+    std::function<void()> callback;\r
+    ComponentPeer* lastPeer = nullptr;\r
+\r
+    JUCE_DECLARE_NON_COPYABLE (VBlankAttachment)\r
+};\r
+\r
+} // namespace juce\r
index da5b4a9a3ecd3d27671794b2845cbcb40c57b498..dd4345297d547dc15be3f79020f1df3def67f1de 100644 (file)
@@ -476,6 +476,11 @@ CodeEditorComponent::CodeEditorComponent (CodeDocument& doc, CodeTokeniser* cons
 \r
 CodeEditorComponent::~CodeEditorComponent()\r
 {\r
+    giveAwayKeyboardFocus();\r
+\r
+    if (auto* peer = getPeer())\r
+        peer->refreshTextInputTarget();\r
+\r
     document.removeListener (pimpl.get());\r
 }\r
 \r
@@ -670,10 +675,9 @@ void CodeEditorComponent::codeDocumentChanged (const int startIndex, const int e
     updateScrollBars();\r
 }\r
 \r
-void CodeEditorComponent::retokenise (int startIndex, int endIndex)\r
+void CodeEditorComponent::retokenise (int startIndex, [[maybe_unused]] int endIndex)\r
 {\r
     const CodeDocument::Position affectedTextStart (document, startIndex);\r
-    juce::ignoreUnused (endIndex); // Leave room for more efficient impl in future.\r
 \r
     clearCachedIterators (affectedTextStart.getLineNumber());\r
 \r
index bb99430f51c010780f1995387648dfac8be04175..f789948fdca4373f8e9074dc914dafddd31a1e5f 100644 (file)
@@ -107,6 +107,11 @@ public:
     */\r
     bool areMouseEventsAllowed() const noexcept                 { return mouseEventsAllowed; }\r
 \r
+    //==============================================================================\r
+    /** Set an instance of IDispatch where dispatch events should be delivered to\r
+    */\r
+    void setEventHandler (void* eventHandler);\r
+\r
     //==============================================================================\r
     /** @internal */\r
     void paint (Graphics&) override;\r
index 98760295e78096e4b8ca4e3c2823c4692ba1ee5a..a935de750309f899c8b354a0111f571eee7a5358 100644 (file)
@@ -71,6 +71,12 @@ public:
     /** Resizes this component to fit the view that it contains. */\r
     void resizeToFitView();\r
 \r
+    /** Resizes the NSView to match the bounds of this component.\r
+\r
+        Most of the time, this will be done for you automatically.\r
+    */\r
+    void resizeViewToFit();\r
+\r
     //==============================================================================\r
     /** @internal */\r
     void paint (Graphics&) override;\r
index 4f60cb8fc9aeb9bb63529784404c90f299acf3e6..9a50b88b42e7fc39618b36a399c8d3edf851310e 100644 (file)
 #include "misc/juce_SystemTrayIconComponent.cpp"\r
 #include "misc/juce_LiveConstantEditor.cpp"\r
 #include "misc/juce_AnimatedAppComponent.cpp"\r
+#include "misc/juce_WebBrowserComponent.cpp"\r
 \r
 //==============================================================================\r
 #if JUCE_MAC || JUCE_IOS\r
 #elif JUCE_LINUX || JUCE_BSD\r
  JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wzero-as-null-pointer-constant")\r
 \r
+ #include <juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h>\r
  #include "native/juce_linux_XEmbedComponent.cpp"\r
 \r
  #if JUCE_WEB_BROWSER\r
   #include "native/juce_android_WebBrowserComponent.cpp"\r
  #endif\r
 #endif\r
-\r
-//==============================================================================\r
-#if ! JUCE_WINDOWS && JUCE_WEB_BROWSER\r
- juce::WebBrowserComponent::WebBrowserComponent (ConstructWithoutPimpl) {}\r
- juce::WindowsWebView2WebBrowserComponent::WindowsWebView2WebBrowserComponent (bool unloadWhenHidden,\r
-                                                                               const WebView2Preferences&)\r
-     : WebBrowserComponent (unloadWhenHidden) {}\r
-#endif\r
index 7dd7c685a04e3b2656a0974d918139cb435605af..f431570f163baee3b6d60c2fb53f327a455c2b89 100644 (file)
 \r
   ID:                     juce_gui_extra\r
   vendor:                 juce\r
-  version:                7.0.2\r
+  version:                7.0.5\r
   name:                   JUCE extended GUI classes\r
   description:            Miscellaneous GUI classes for specialised tasks.\r
   website:                http://www.juce.com/juce\r
   license:                GPL/Commercial\r
-  minimumCppStandard:     14\r
+  minimumCppStandard:     17\r
 \r
   dependencies:           juce_gui_basics\r
   OSXFrameworks:          WebKit\r
index f2798e483a302ef147c887475a773adaa5c043e3..ab2b8fcb3ccbb9448628eec5cd87a7a0e3602881 100644 (file)
@@ -27,15 +27,41 @@ namespace juce
 {\r
 \r
 AnimatedAppComponent::AnimatedAppComponent()\r
-    : lastUpdateTime (Time::getCurrentTime()), totalUpdates (0)\r
 {\r
     setOpaque (true);\r
 }\r
 \r
-void AnimatedAppComponent::setFramesPerSecond (int framesPerSecond)\r
+void AnimatedAppComponent::setFramesPerSecond (int framesPerSecondIn)\r
 {\r
-    jassert (framesPerSecond > 0 && framesPerSecond < 1000);\r
-    startTimerHz (framesPerSecond);\r
+    jassert (0 < framesPerSecond && framesPerSecond < 1000);\r
+    framesPerSecond = framesPerSecondIn;\r
+    updateSync();\r
+}\r
+\r
+void AnimatedAppComponent::updateSync()\r
+{\r
+    if (useVBlank)\r
+    {\r
+        stopTimer();\r
+\r
+        if (vBlankAttachment.isEmpty())\r
+            vBlankAttachment = { this, [this] { timerCallback(); } };\r
+    }\r
+    else\r
+    {\r
+        vBlankAttachment = {};\r
+\r
+        const auto interval = 1000 / framesPerSecond;\r
+\r
+        if (getTimerInterval() != interval)\r
+            startTimer (interval);\r
+    }\r
+}\r
+\r
+void AnimatedAppComponent::setSynchroniseToVBlank (bool syncToVBlank)\r
+{\r
+    useVBlank = syncToVBlank;\r
+    updateSync();\r
 }\r
 \r
 int AnimatedAppComponent::getMillisecondsSinceLastUpdate() const noexcept\r
index b4e55a8100c180dc1d1c22ecfe8994f1898f654e..18d5db10bd24a17dc7739f57ab68005a7058e5bf 100644 (file)
@@ -36,8 +36,8 @@ namespace juce
 \r
     @tags{GUI}\r
 */\r
-class AnimatedAppComponent   : public Component,\r
-                               private Timer\r
+class JUCE_API  AnimatedAppComponent   : public Component,\r
+                                         private Timer\r
 {\r
 public:\r
     AnimatedAppComponent();\r
@@ -47,6 +47,11 @@ public:
     */\r
     void setFramesPerSecond (int framesPerSecond);\r
 \r
+    /** You can use this function to synchronise animation updates with the current display's vblank\r
+        events. When this mode is enabled the value passed to setFramesPerSecond() is ignored.\r
+    */\r
+    void setSynchroniseToVBlank (bool syncToVBlank);\r
+\r
     /** Called periodically, at the frequency specified by setFramesPerSecond().\r
         This is a the best place to do things like advancing animation parameters,\r
         checking the mouse position, etc.\r
@@ -66,8 +71,13 @@ public:
 \r
 private:\r
     //==============================================================================\r
-    Time lastUpdateTime;\r
-    int totalUpdates;\r
+    void updateSync();\r
+\r
+    Time lastUpdateTime = Time::getCurrentTime();\r
+    int totalUpdates = 0;\r
+    int framesPerSecond = 60;\r
+    bool useVBlank = false;\r
+    VBlankAttachment vBlankAttachment;\r
 \r
     void timerCallback() override;\r
 \r
index 5642deb8aabadbd8c3b9c9c5c92cc58176dce99d..ece6c622dafda2dad7b306f800f15848bb1ff645 100644 (file)
@@ -86,12 +86,11 @@ PushNotifications::~PushNotifications() { clearSingletonInstance(); }
 void PushNotifications::addListener (Listener* l)      { listeners.add (l); }\r
 void PushNotifications::removeListener (Listener* l)   { listeners.remove (l); }\r
 \r
-void PushNotifications::requestPermissionsWithSettings (const PushNotifications::Settings& settings)\r
+void PushNotifications::requestPermissionsWithSettings ([[maybe_unused]] const PushNotifications::Settings& settings)\r
 {\r
   #if JUCE_PUSH_NOTIFICATIONS && (JUCE_IOS || JUCE_MAC)\r
     pimpl->requestPermissionsWithSettings (settings);\r
   #else\r
-    ignoreUnused (settings);\r
     listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); });\r
   #endif\r
 }\r
@@ -137,12 +136,10 @@ String PushNotifications::getDeviceToken() const
   #endif\r
 }\r
 \r
-void PushNotifications::setupChannels (const Array<ChannelGroup>& groups, const Array<Channel>& channels)\r
+void PushNotifications::setupChannels ([[maybe_unused]] const Array<ChannelGroup>& groups, [[maybe_unused]] const Array<Channel>& channels)\r
 {\r
   #if JUCE_PUSH_NOTIFICATIONS\r
     pimpl->setupChannels (groups, channels);\r
-  #else\r
-    ignoreUnused (groups, channels);\r
   #endif\r
 }\r
 \r
@@ -160,58 +157,48 @@ void PushNotifications::removeAllPendingLocalNotifications()
   #endif\r
 }\r
 \r
-void PushNotifications::subscribeToTopic (const String& topic)\r
+void PushNotifications::subscribeToTopic ([[maybe_unused]] const String& topic)\r
 {\r
   #if JUCE_PUSH_NOTIFICATIONS\r
     pimpl->subscribeToTopic (topic);\r
-  #else\r
-    ignoreUnused (topic);\r
   #endif\r
 }\r
 \r
-void PushNotifications::unsubscribeFromTopic (const String& topic)\r
+void PushNotifications::unsubscribeFromTopic ([[maybe_unused]] const String& topic)\r
 {\r
   #if JUCE_PUSH_NOTIFICATIONS\r
     pimpl->unsubscribeFromTopic (topic);\r
-  #else\r
-    ignoreUnused (topic);\r
   #endif\r
 }\r
 \r
 \r
-void PushNotifications::sendLocalNotification (const Notification& n)\r
+void PushNotifications::sendLocalNotification ([[maybe_unused]] const Notification& n)\r
 {\r
   #if JUCE_PUSH_NOTIFICATIONS\r
     pimpl->sendLocalNotification (n);\r
-  #else\r
-    ignoreUnused (n);\r
   #endif\r
 }\r
 \r
-void PushNotifications::removeDeliveredNotification (const String& identifier)\r
+void PushNotifications::removeDeliveredNotification ([[maybe_unused]] const String& identifier)\r
 {\r
   #if JUCE_PUSH_NOTIFICATIONS\r
     pimpl->removeDeliveredNotification (identifier);\r
-  #else\r
-    ignoreUnused (identifier);\r
   #endif\r
 }\r
 \r
-void PushNotifications::removePendingLocalNotification (const String& identifier)\r
+void PushNotifications::removePendingLocalNotification ([[maybe_unused]] const String& identifier)\r
 {\r
   #if JUCE_PUSH_NOTIFICATIONS\r
     pimpl->removePendingLocalNotification (identifier);\r
-  #else\r
-    ignoreUnused (identifier);\r
   #endif\r
 }\r
 \r
-void PushNotifications::sendUpstreamMessage (const String& serverSenderId,\r
-                                             const String& collapseKey,\r
-                                             const String& messageId,\r
-                                             const String& messageType,\r
-                                             int timeToLive,\r
-                                             const StringPairArray& additionalData)\r
+void PushNotifications::sendUpstreamMessage ([[maybe_unused]] const String& serverSenderId,\r
+                                             [[maybe_unused]] const String& collapseKey,\r
+                                             [[maybe_unused]] const String& messageId,\r
+                                             [[maybe_unused]] const String& messageType,\r
+                                             [[maybe_unused]] int timeToLive,\r
+                                             [[maybe_unused]] const StringPairArray& additionalData)\r
 {\r
   #if JUCE_PUSH_NOTIFICATIONS\r
     pimpl->sendUpstreamMessage (serverSenderId,\r
@@ -220,10 +207,24 @@ void PushNotifications::sendUpstreamMessage (const String& serverSenderId,
                                 messageType,\r
                                 timeToLive,\r
                                 additionalData);\r
-  #else\r
-    ignoreUnused (serverSenderId, collapseKey, messageId, messageType);\r
-    ignoreUnused (timeToLive, additionalData);\r
   #endif\r
 }\r
 \r
+//==============================================================================\r
+void PushNotifications::Listener::notificationSettingsReceived ([[maybe_unused]] const Settings& settings) {}\r
+void PushNotifications::Listener::pendingLocalNotificationsListReceived ([[maybe_unused]] const Array<Notification>& notifications) {}\r
+void PushNotifications::Listener::handleNotification ([[maybe_unused]] bool isLocalNotification,\r
+                                                      [[maybe_unused]] const Notification& notification) {}\r
+void PushNotifications::Listener::handleNotificationAction ([[maybe_unused]] bool isLocalNotification,\r
+                                                            [[maybe_unused]] const Notification& notification,\r
+                                                            [[maybe_unused]] const String& actionIdentifier,\r
+                                                            [[maybe_unused]] const String& optionalResponse) {}\r
+void PushNotifications::Listener::localNotificationDismissedByUser ([[maybe_unused]] const Notification& notification) {}\r
+void PushNotifications::Listener::deliveredNotificationsListReceived ([[maybe_unused]] const Array<Notification>& notifications) {}\r
+void PushNotifications::Listener::deviceTokenRefreshed ([[maybe_unused]] const String& token) {}\r
+void PushNotifications::Listener::remoteNotificationsDeleted() {}\r
+void PushNotifications::Listener::upstreamMessageSent ([[maybe_unused]] const String& messageId) {}\r
+void PushNotifications::Listener::upstreamMessageSendingError ([[maybe_unused]] const String& messageId,\r
+                                                               [[maybe_unused]] const String& error) {}\r
+\r
 } // namespace juce\r
index 52cf1dbce2897730a04545b9619fc18d7c791dd5..384b43abfbc2d09ebe920356d262ce535f851a9e 100644 (file)
@@ -601,12 +601,12 @@ public:
             with no categories and all allow flags set to true will be received in\r
             Listener::notificationSettingsReceived().\r
         */\r
-        virtual void notificationSettingsReceived (const Settings& settings) { ignoreUnused (settings); }\r
+        virtual void notificationSettingsReceived (const Settings& settings);\r
 \r
         /** Called when the list of pending notifications, requested by calling\r
             getPendingLocalNotifications() is returned. iOS 10 or above only.\r
         */\r
-        virtual void pendingLocalNotificationsListReceived (const Array<Notification>& notifications) { ignoreUnused (notifications); }\r
+        virtual void pendingLocalNotificationsListReceived (const Array<Notification>& notifications);\r
 \r
         /** This can be called in multiple different situations, depending on the OS and the situation.\r
 \r
@@ -622,7 +622,7 @@ public:
 \r
             Note you can receive this callback on startup, if the application was launched from a notification.\r
         */\r
-        virtual void handleNotification (bool isLocalNotification, const Notification& notification) { ignoreUnused (isLocalNotification); ignoreUnused (notification); }\r
+        virtual void handleNotification (bool isLocalNotification, const Notification& notification);\r
 \r
         /** This can be called when a user performs some action on the notification such as\r
             pressing on an action button or responding with a text input.\r
@@ -641,18 +641,12 @@ public:
         virtual void handleNotificationAction (bool isLocalNotification,\r
                                                const Notification& notification,\r
                                                const String& actionIdentifier,\r
-                                               const String& optionalResponse)\r
-        {\r
-            ignoreUnused (isLocalNotification);\r
-            ignoreUnused (notification);\r
-            ignoreUnused (actionIdentifier);\r
-            ignoreUnused (optionalResponse);\r
-        }\r
+                                               const String& optionalResponse);\r
 \r
         /** For iOS10 and Android, this can be also called when a user dismissed the notification before\r
             responding to it.\r
         */\r
-        virtual void localNotificationDismissedByUser (const Notification& notification) { ignoreUnused (notification); }\r
+        virtual void localNotificationDismissedByUser (const Notification& notification);\r
 \r
         /** Called after getDeliveredNotifications() request is fulfilled. Returns notifications\r
             that are visible in the notification area on the device and that are still waiting\r
@@ -661,31 +655,31 @@ public:
             On iOS, iOS version 10 or higher is required. On Android, API level 18 or higher is required.\r
             For unsupported platforms, an empty array will be returned.\r
          */\r
-        virtual void deliveredNotificationsListReceived (const Array<Notification>& notifications) { ignoreUnused (notifications); }\r
+        virtual void deliveredNotificationsListReceived (const Array<Notification>& notifications);\r
 \r
         /** Called whenever a token gets refreshed. You should monitor any token updates, because\r
             only the last token that is assigned to device is valid and can be used.\r
         */\r
-        virtual void deviceTokenRefreshed (const String& token) { ignoreUnused (token); }\r
+        virtual void deviceTokenRefreshed (const String& token);\r
 \r
         /** Called when Firebase Cloud Messaging server deletes pending messages. This can happen when\r
             1) too many messages were sent to the server (hint: use collapsible messages).\r
             2) the devices hasn't been online in a long time (refer to Firebase documentation for\r
                the maximum time a message can be stored on FCM before expiring).\r
         */\r
-        virtual void remoteNotificationsDeleted() {}\r
+        virtual void remoteNotificationsDeleted();\r
 \r
         /** Called when an upstream message sent with PushNotifications::sendUpstreamMessage() has been\r
             sent successfully.\r
             Bear in mind that in may take several minutes or more to receive this callback.\r
         */\r
-        virtual void upstreamMessageSent (const String& messageId) { ignoreUnused (messageId); }\r
+        virtual void upstreamMessageSent (const String& messageId);\r
 \r
         /** Called when there was an error sending an upstream message with\r
             PushNotifications::sendUpstreamMessage().\r
             Bear in mind that in may take several minutes or more to receive this callback.\r
         */\r
-        virtual void upstreamMessageSendingError (const String& messageId, const String& error) {  ignoreUnused (messageId); ignoreUnused (error); }\r
+        virtual void upstreamMessageSendingError (const String& messageId, const String& error);\r
     };\r
 \r
     void addListener (Listener* l);\r
index 94fb32631352d75652347d0e6782e2169ea35f97..c5a4efb8d8c589f532c4a52a3b6a7d8c76ccdd2b 100644 (file)
@@ -132,19 +132,17 @@ void RecentlyOpenedFilesList::restoreFromString (const String& stringifiedVersio
 \r
 \r
 //==============================================================================\r
-void RecentlyOpenedFilesList::registerRecentFileNatively (const File& file)\r
+void RecentlyOpenedFilesList::registerRecentFileNatively ([[maybe_unused]] const File& file)\r
 {\r
    #if JUCE_MAC\r
     JUCE_AUTORELEASEPOOL\r
     {\r
         [[NSDocumentController sharedDocumentController] noteNewRecentDocumentURL: createNSURLFromFile (file)];\r
     }\r
-   #else\r
-    ignoreUnused (file);\r
    #endif\r
 }\r
 \r
-void RecentlyOpenedFilesList::forgetRecentFileNatively (const File& file)\r
+void RecentlyOpenedFilesList::forgetRecentFileNatively ([[maybe_unused]] const File& file)\r
 {\r
    #if JUCE_MAC\r
     JUCE_AUTORELEASEPOOL\r
@@ -166,8 +164,6 @@ void RecentlyOpenedFilesList::forgetRecentFileNatively (const File& file)
             if (! [url isEqual:nsFile])\r
                 [sharedDocController noteNewRecentDocumentURL:url];\r
     }\r
-   #else\r
-    ignoreUnused (file);\r
    #endif\r
 }\r
 \r
diff --git a/modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp b/modules/juce_gui_extra/misc/juce_WebBrowserComponent.cpp
new file mode 100644 (file)
index 0000000..ce8af6e
--- /dev/null
@@ -0,0 +1,39 @@
+/*\r
+  ==============================================================================\r
+\r
+   This file is part of the JUCE library.\r
+   Copyright (c) 2022 - Raw Material Software Limited\r
+\r
+   JUCE is an open source library subject to commercial or open-source\r
+   licensing.\r
+\r
+   By using JUCE, you agree to the terms of both the JUCE 7 End-User License\r
+   Agreement and JUCE Privacy Policy.\r
+\r
+   End User License Agreement: www.juce.com/juce-7-licence\r
+   Privacy Policy: www.juce.com/juce-privacy-policy\r
+\r
+   Or: You may also use this code under the terms of the GPL v3 (see\r
+   www.gnu.org/licenses).\r
+\r
+   JUCE IS PROVIDED "AS IS" WITHOUT ANY WARRANTY, AND ALL WARRANTIES, WHETHER\r
+   EXPRESSED OR IMPLIED, INCLUDING MERCHANTABILITY AND FITNESS FOR PURPOSE, ARE\r
+   DISCLAIMED.\r
+\r
+  ==============================================================================\r
+*/\r
+\r
+namespace juce\r
+{\r
+\r
+#if JUCE_WEB_BROWSER || DOXYGEN\r
+\r
+bool WebBrowserComponent::pageAboutToLoad ([[maybe_unused]] const String& newURL)             { return true; }\r
+void WebBrowserComponent::pageFinishedLoading ([[maybe_unused]] const String& url)            {}\r
+bool WebBrowserComponent::pageLoadHadNetworkError ([[maybe_unused]] const String& errorInfo)  { return true; }\r
+void WebBrowserComponent::windowCloseRequest()                                                {}\r
+void WebBrowserComponent::newWindowAttemptingToLoad ([[maybe_unused]] const String& newURL)   {}\r
+\r
+#endif\r
+\r
+} // namespace juce\r
index 3ecdc5a626f22d4ac6dc0fe87177dc1bde49b0f5..758d2587ea504489b255ae504835f67d12de3f18 100644 (file)
@@ -46,21 +46,149 @@ class JUCE_API  WebBrowserComponent  : public Component
 {\r
 public:\r
     //==============================================================================\r
+    class JUCE_API Options\r
+    {\r
+    public:\r
+        //==============================================================================\r
+        enum class Backend\r
+        {\r
+            /**\r
+                Default web browser backend. WebKit will be used on macOS, gtk-webkit2 on Linux and internet\r
+                explorer on Windows. On Windows, the default may change to webview2 in the fututre.\r
+            */\r
+            defaultBackend,\r
+\r
+            /**\r
+                Use Internet Explorer as the backend on Windows. By default, IE will use an ancient version\r
+                of IE. To change this behaviour, you either need to add the following html element into your page's\r
+                head section:\r
+\r
+                    <meta http-equiv="X-UA-Compatible" content="IE=edge" />\r
+\r
+                or you need to change windows registry values for your application.  More infromation on the latter\r
+                can be found here:\r
+\r
+                https://learn.microsoft.com/en-us/previous-versions/windows/internet-explorer/ie-developer/general-info/ee330730(v=vs.85)?redirectedfrom=MSDN#browser-emulation\r
+            */\r
+            ie,\r
+\r
+            /**\r
+                Use the chromium based  WebView2 engine on Windows\r
+            */\r
+            webview2\r
+        };\r
+\r
+        /**\r
+            Use a particular backend to create the WebViewBrowserComponent. JUCE will silently\r
+            fallback to the default backend if the selected backend is not supported. To check\r
+            if a specific backend is supported on your platform or not, use\r
+            WebBrowserComponent::areOptionsSupported.\r
+        */\r
+        [[nodiscard]] Options withBackend (Backend backend) const              { return withMember (*this, &Options::browserBackend, backend); }\r
+\r
+        //==============================================================================\r
+        /**\r
+            Tell JUCE to keep the web page alive when the WebBrowserComponent is not visible.\r
+            By default, JUCE will replace the current page with a blank page - this can be\r
+            handy to stop the browser using resources in the background when it's not\r
+            actually being used.\r
+        */\r
+        [[nodiscard]] Options withKeepPageLoadedWhenBrowserIsHidden () const   { return withMember (*this, &Options::keepPageLoadedWhenBrowserIsHidden, true); }\r
+\r
+        /**\r
+            Use a specific user agent string when requesting web pages.\r
+        */\r
+        [[nodiscard]] Options withUserAgent (String ua) const                  { return withMember (*this, &Options::userAgent, std::move (ua)); }\r
+\r
+        //==============================================================================\r
+        /** Options specific to the WebView2 backend. These options will be ignored\r
+            if another backend is used.\r
+        */\r
+        class WinWebView2\r
+        {\r
+        public:\r
+            //==============================================================================\r
+            /** Sets a custom location for the WebView2Loader.dll that is not a part of the\r
+                standard system DLL search paths.\r
+            */\r
+            [[nodiscard]] WinWebView2 withDLLLocation (const File& location) const   { return withMember (*this, &WinWebView2::dllLocation, location); }\r
+\r
+            /** Sets a non-default location for storing user data for the browser instance. */\r
+            [[nodiscard]] WinWebView2 withUserDataFolder (const File& folder) const  { return withMember (*this, &WinWebView2::userDataFolder, folder); }\r
+\r
+            /** If this is set, the status bar usually displayed in the lower-left of the webview\r
+                will be disabled.\r
+            */\r
+            [[nodiscard]] WinWebView2 withStatusBarDisabled() const                  { return withMember (*this, &WinWebView2::disableStatusBar, true); }\r
+\r
+            /** If this is set, a blank page will be displayed on error instead of the default\r
+                built-in error page.\r
+            */\r
+            [[nodiscard]] WinWebView2 withBuiltInErrorPageDisabled() const           { return withMember (*this, &WinWebView2::disableBuiltInErrorPage, true); }\r
+\r
+            /** Sets the background colour that WebView2 renders underneath all web content.\r
+\r
+                This colour must either be fully opaque or transparent. On Windows 7 this\r
+                colour must be opaque.\r
+            */\r
+            [[nodiscard]] WinWebView2 withBackgroundColour (const Colour& colour) const\r
+            {\r
+                // the background colour must be either fully opaque or transparent!\r
+                jassert (colour.isOpaque() || colour.isTransparent());\r
+\r
+                return withMember (*this, &WinWebView2::backgroundColour, colour);\r
+            }\r
+\r
+            //==============================================================================\r
+            File getDLLLocation() const                          { return dllLocation; }\r
+            File getUserDataFolder() const                       { return userDataFolder; }\r
+            bool getIsStatusBarDisabled() const noexcept         { return disableStatusBar; }\r
+            bool getIsBuiltInErrorPageDisabled() const noexcept  { return disableBuiltInErrorPage; }\r
+            Colour getBackgroundColour() const                   { return backgroundColour; }\r
+\r
+        private:\r
+            //==============================================================================\r
+            File dllLocation, userDataFolder;\r
+            bool disableStatusBar = false, disableBuiltInErrorPage = false;\r
+            Colour backgroundColour;\r
+        };\r
+\r
+        [[nodiscard]] Options withWinWebView2Options (const WinWebView2& winWebView2Options) const\r
+        {\r
+            return withMember (*this, &Options::winWebView2, winWebView2Options);\r
+        }\r
+\r
+        //==============================================================================\r
+        Backend getBackend() const noexcept                       { return browserBackend; }\r
+        bool keepsPageLoadedWhenBrowserIsHidden() const noexcept  { return keepPageLoadedWhenBrowserIsHidden; }\r
+        String getUserAgent() const                               { return userAgent; }\r
+        WinWebView2 getWinWebView2BackendOptions() const          { return winWebView2; }\r
+\r
+    private:\r
+        //==============================================================================\r
+        Backend browserBackend = Backend::defaultBackend;\r
+        bool keepPageLoadedWhenBrowserIsHidden = false;\r
+        String userAgent;\r
+        WinWebView2 winWebView2;\r
+    };\r
+\r
+    //==============================================================================\r
+    /** Creates a WebBrowserComponent with default options*/\r
+    WebBrowserComponent() : WebBrowserComponent (Options {}) {}\r
+\r
     /** Creates a WebBrowserComponent.\r
 \r
         Once it's created and visible, send the browser to a URL using goToURL().\r
-\r
-        @param unloadPageWhenBrowserIsHidden  if this is true, then when the browser\r
-                            component is taken offscreen, it'll clear the current page\r
-                            and replace it with a blank page - this can be handy to stop\r
-                            the browser using resources in the background when it's not\r
-                            actually being used.\r
     */\r
-    explicit WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true);\r
+    explicit WebBrowserComponent (const Options& options);\r
 \r
     /** Destructor. */\r
     ~WebBrowserComponent() override;\r
 \r
+    //==============================================================================\r
+    /** Check if the specified options are supported on this platform. */\r
+    static bool areOptionsSupported (const Options& options);\r
+\r
     //==============================================================================\r
     /** Sends the browser to a particular URL.\r
 \r
@@ -98,10 +226,10 @@ public:
         tries to go to a particular URL. To allow the operation to carry on,\r
         return true, or return false to stop the navigation happening.\r
     */\r
-    virtual bool pageAboutToLoad (const String& newURL)             { ignoreUnused (newURL); return true; }\r
+    virtual bool pageAboutToLoad (const String& newURL);\r
 \r
     /** This callback happens when the browser has finished loading a page. */\r
-    virtual void pageFinishedLoading (const String& url)            { ignoreUnused (url); }\r
+    virtual void pageFinishedLoading (const String& url);\r
 \r
     /** This callback happens when a network error was encountered while\r
         trying to load a page.\r
@@ -113,18 +241,18 @@ public:
         The errorInfo contains some platform dependent string describing the\r
         error.\r
     */\r
-    virtual bool pageLoadHadNetworkError (const String& errorInfo)  { ignoreUnused (errorInfo); return true; }\r
+    virtual bool pageLoadHadNetworkError (const String& errorInfo);\r
 \r
     /** This callback occurs when a script or other activity in the browser asks for\r
         the window to be closed.\r
     */\r
-    virtual void windowCloseRequest()                               {}\r
+    virtual void windowCloseRequest();\r
 \r
     /** This callback occurs when the browser attempts to load a URL in a new window.\r
         This won't actually load the window but gives you a chance to either launch a\r
         new window yourself or just load the URL into the current window with goToURL().\r
      */\r
-    virtual void newWindowAttemptingToLoad (const String& newURL)   { ignoreUnused (newURL); }\r
+    virtual void newWindowAttemptingToLoad (const String& newURL);\r
 \r
     //==============================================================================\r
     /** @internal */\r
@@ -141,17 +269,6 @@ public:
     /** @internal */\r
     class Pimpl;\r
 \r
-protected:\r
-    friend class WindowsWebView2WebBrowserComponent;\r
-\r
-    /** @internal */\r
-    struct ConstructWithoutPimpl\r
-    {\r
-        explicit ConstructWithoutPimpl (bool unloadOnHide) : unloadWhenHidden (unloadOnHide) {}\r
-        const bool unloadWhenHidden;\r
-    };\r
-    explicit WebBrowserComponent (ConstructWithoutPimpl);\r
-\r
 private:\r
     //==============================================================================\r
     std::unique_ptr<Pimpl> browser;\r
@@ -166,122 +283,6 @@ private:
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (WebBrowserComponent)\r
 };\r
 \r
-//==============================================================================\r
-/** Class used to create a set of preferences to pass to the WindowsWebView2WebBrowserComponent\r
-    wrapper constructor to modify aspects of its behaviour and settings.\r
-\r
-    You can chain together a series of calls to this class's methods to create a set of whatever\r
-    preferences you want to specify.\r
-\r
-    @tags{GUI}\r
-*/\r
-class JUCE_API  WebView2Preferences\r
-{\r
-public:\r
-    //==============================================================================\r
-    /** Sets a custom location for the WebView2Loader.dll that is not a part of the\r
-        standard system DLL search paths.\r
-    */\r
-    JUCE_NODISCARD WebView2Preferences withDLLLocation (const File& location) const   { return with (&WebView2Preferences::dllLocation, location); }\r
-\r
-    /** Sets a non-default location for storing user data for the browser instance. */\r
-    WebView2Preferences withUserDataFolder (const File& folder) const  { return with (&WebView2Preferences::userDataFolder, folder); }\r
-\r
-    /** If this is set, the status bar usually displayed in the lower-left of the webview\r
-        will be disabled.\r
-    */\r
-    JUCE_NODISCARD WebView2Preferences withStatusBarDisabled() const                  { return with (&WebView2Preferences::disableStatusBar, true); }\r
-\r
-    /** If this is set, a blank page will be displayed on error instead of the default\r
-        built-in error page.\r
-    */\r
-    JUCE_NODISCARD WebView2Preferences withBuiltInErrorPageDisabled() const           { return with (&WebView2Preferences::disableBuiltInErrorPage, true); }\r
-\r
-    /** Sets the background colour that WebView2 renders underneath all web content.\r
-\r
-        This colour must either be fully opaque or transparent. On Windows 7 this\r
-        colour must be opaque.\r
-    */\r
-    JUCE_NODISCARD WebView2Preferences withBackgroundColour (const Colour& colour) const\r
-    {\r
-        // the background colour must be either fully opaque or transparent!\r
-        jassert (colour.isOpaque() || colour.isTransparent());\r
-\r
-        return with (&WebView2Preferences::backgroundColour, colour);\r
-    }\r
-\r
-    //==============================================================================\r
-    File getDLLLocation() const                          { return dllLocation; }\r
-    File getUserDataFolder() const                       { return userDataFolder; }\r
-    bool getIsStatusBarDisabled() const noexcept         { return disableStatusBar; }\r
-    bool getIsBuiltInErrorPageDisabled() const noexcept  { return disableBuiltInErrorPage; }\r
-    Colour getBackgroundColour() const                   { return backgroundColour; }\r
-\r
-private:\r
-    //==============================================================================\r
-    template <typename Member, typename Item>\r
-    WebView2Preferences with (Member&& member, Item&& item) const\r
-    {\r
-        auto options = *this;\r
-        options.*member = std::forward<Item> (item);\r
-\r
-        return options;\r
-    }\r
-\r
-    File dllLocation, userDataFolder;\r
-    bool disableStatusBar = false, disableBuiltInErrorPage = false;\r
-    Colour backgroundColour = Colours::white;\r
-};\r
-\r
-/**\r
-    If you have enabled the JUCE_USE_WIN_WEBVIEW2 flag then this wrapper will attempt to\r
-    use the Microsoft Edge (Chromium) WebView2 control instead of IE on Windows. It will\r
-    behave the same as WebBrowserComponent on all other platforms and will fall back to\r
-    IE on Windows if the WebView2 requirements are not met.\r
-\r
-    This requires Microsoft Edge (minimum version 82.0.488.0) to be installed at runtime.\r
-\r
-    Currently this also requires that WebView2Loader.dll, which can be found in the\r
-    Microsoft.Web.WebView package, is installed at runtime. As this is not a standard\r
-    system DLL, we can't rely on it being found via the normal system DLL search paths.\r
-    Therefore in order to use WebView2 you need to ensure that WebView2Loader.dll is\r
-    installed either to a location covered by the Windows DLL system search paths or\r
-    to the folder specified in the WebView2Preferences.\r
-\r
-    @tags{GUI}\r
-*/\r
-class WindowsWebView2WebBrowserComponent  : public WebBrowserComponent\r
-{\r
-public:\r
-    //==============================================================================\r
-    /** Creates a WebBrowserComponent that is compatible with the WebView2 control\r
-        on Windows.\r
-\r
-        @param unloadPageWhenBrowserIsHidden  if this is true, then when the browser\r
-                               component is taken offscreen, it'll clear the current page\r
-                               and replace it with a blank page - this can be handy to stop\r
-                               the browser using resources in the background when it's not\r
-                               actually being used.\r
-        @param preferences     a set of preferences used to control aspects of the webview's\r
-                               behaviour.\r
-\r
-        @see WebView2Preferences\r
-    */\r
-    WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,\r
-                                        const WebView2Preferences& preferences = {});\r
-\r
-    // This constructor has been deprecated. Use the new constructor that takes a\r
-    // WebView2Preferences instead.\r
-    explicit WindowsWebView2WebBrowserComponent (bool unloadPageWhenBrowserIsHidden = true,\r
-                                                 const File& dllLocation = {},\r
-                                                 const File& userDataFolder = {})\r
-                                  : WindowsWebView2WebBrowserComponent (unloadPageWhenBrowserIsHidden,\r
-                                                                        WebView2Preferences().withDLLLocation (dllLocation)\r
-                                                                                             .withUserDataFolder (userDataFolder))\r
-    {\r
-    }\r
-};\r
-\r
 #endif\r
 \r
 } // namespace juce\r
index 87b461c05cb90f908e53aa36778bc88b07e29b04..b382a3b9e35734de7e7f656c649d1f687a8bc386 100644 (file)
@@ -447,20 +447,18 @@ struct PushNotifications::Pimpl
       #endif\r
     }\r
 \r
-    void notifyListenersTokenRefreshed (const String& token)\r
+    void notifyListenersTokenRefreshed ([[maybe_unused]] const String& token)\r
     {\r
       #if defined(JUCE_FIREBASE_INSTANCE_ID_SERVICE_CLASSNAME)\r
         MessageManager::callAsync ([this, token]\r
         {\r
             owner.listeners.call ([&] (Listener& l) { l.deviceTokenRefreshed (token); });\r
         });\r
-      #else\r
-        ignoreUnused (token);\r
       #endif\r
     }\r
 \r
     //==============================================================================\r
-    void subscribeToTopic (const String& topic)\r
+    void subscribeToTopic ([[maybe_unused]] const String& topic)\r
     {\r
       #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)\r
         auto* env = getEnv();\r
@@ -469,12 +467,10 @@ struct PushNotifications::Pimpl
                                                                                  FirebaseMessaging.getInstance));\r
 \r
         env->CallObjectMethod (firebaseMessaging, FirebaseMessaging.subscribeToTopic, javaString (topic).get());\r
-      #else\r
-        ignoreUnused (topic);\r
       #endif\r
     }\r
 \r
-    void unsubscribeFromTopic (const String& topic)\r
+    void unsubscribeFromTopic ([[maybe_unused]] const String& topic)\r
     {\r
       #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)\r
         auto* env = getEnv();\r
@@ -483,17 +479,15 @@ struct PushNotifications::Pimpl
                                                                                  FirebaseMessaging.getInstance));\r
 \r
         env->CallObjectMethod (firebaseMessaging, FirebaseMessaging.unsubscribeFromTopic, javaString (topic).get());\r
-      #else\r
-        ignoreUnused (topic);\r
       #endif\r
     }\r
 \r
-    void sendUpstreamMessage (const String& serverSenderId,\r
-                              const String& collapseKey,\r
-                              const String& messageId,\r
-                              const String& messageType,\r
-                              int timeToLive,\r
-                              const StringPairArray& additionalData)\r
+    void sendUpstreamMessage ([[maybe_unused]] const String& serverSenderId,\r
+                              [[maybe_unused]] const String& collapseKey,\r
+                              [[maybe_unused]] const String& messageId,\r
+                              [[maybe_unused]] const String& messageType,\r
+                              [[maybe_unused]] int timeToLive,\r
+                              [[maybe_unused]] const StringPairArray& additionalData)\r
     {\r
       #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)\r
         auto* env = getEnv();\r
@@ -521,13 +515,10 @@ struct PushNotifications::Pimpl
                                                                                  FirebaseMessaging.getInstance));\r
 \r
         env->CallVoidMethod (firebaseMessaging, FirebaseMessaging.send, message.get());\r
-      #else\r
-        ignoreUnused (serverSenderId, collapseKey, messageId, messageType);\r
-        ignoreUnused (timeToLive, additionalData);\r
       #endif\r
     }\r
 \r
-    void notifyListenersAboutRemoteNotificationFromSystemTray (const LocalRef<jobject>& intent)\r
+    void notifyListenersAboutRemoteNotificationFromSystemTray ([[maybe_unused]] const LocalRef<jobject>& intent)\r
     {\r
       #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)\r
         auto* env = getEnv();\r
@@ -536,12 +527,10 @@ struct PushNotifications::Pimpl
         auto notification = remoteNotificationBundleToJuceNotification (bundle);\r
 \r
         owner.listeners.call ([&] (Listener& l) { l.handleNotification (false, notification); });\r
-      #else\r
-        ignoreUnused (intent);\r
       #endif\r
     }\r
 \r
-    void notifyListenersAboutRemoteNotificationFromService (const LocalRef<jobject>& remoteNotification)\r
+    void notifyListenersAboutRemoteNotificationFromService ([[maybe_unused]] const LocalRef<jobject>& remoteNotification)\r
     {\r
       #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)\r
         GlobalRef rn (remoteNotification);\r
@@ -551,8 +540,6 @@ struct PushNotifications::Pimpl
             auto notification = firebaseRemoteNotificationToJuceNotification (rn.get());\r
             owner.listeners.call ([&] (Listener& l) { l.handleNotification (false, notification); });\r
         });\r
-      #else\r
-        ignoreUnused (remoteNotification);\r
       #endif\r
     }\r
 \r
@@ -566,7 +553,7 @@ struct PushNotifications::Pimpl
       #endif\r
     }\r
 \r
-    void notifyListenersAboutUpstreamMessageSent (const LocalRef<jstring>& messageId)\r
+    void notifyListenersAboutUpstreamMessageSent ([[maybe_unused]] const LocalRef<jstring>& messageId)\r
     {\r
       #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)\r
         GlobalRef mid (LocalRef<jobject>(messageId.get()));\r
@@ -576,13 +563,11 @@ struct PushNotifications::Pimpl
             auto midString = juceString ((jstring) mid.get());\r
             owner.listeners.call ([&] (Listener& l) { l.upstreamMessageSent (midString); });\r
         });\r
-      #else\r
-        ignoreUnused (messageId);\r
       #endif\r
     }\r
 \r
-    void notifyListenersAboutUpstreamMessageSendingError (const LocalRef<jstring>& messageId,\r
-                                                          const LocalRef<jstring>& error)\r
+    void notifyListenersAboutUpstreamMessageSendingError ([[maybe_unused]] const LocalRef<jstring>& messageId,\r
+                                                          [[maybe_unused]] const LocalRef<jstring>& error)\r
     {\r
       #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)\r
         GlobalRef mid (LocalRef<jobject>(messageId.get())), e (LocalRef<jobject>(error.get()));\r
@@ -594,8 +579,6 @@ struct PushNotifications::Pimpl
 \r
             owner.listeners.call ([&] (Listener& l) { l.upstreamMessageSendingError (midString, eString); });\r
         });\r
-      #else\r
-        ignoreUnused (messageId, error);\r
       #endif\r
     }\r
 \r
@@ -1566,8 +1549,6 @@ struct JuceFirebaseInstanceIdService
             instance->pimpl->notifyListenersTokenRefreshed (juceString (static_cast<jstring> (token)));\r
     }\r
 };\r
-\r
-JuceFirebaseInstanceIdService::InstanceIdService_Class JuceFirebaseInstanceIdService::InstanceIdService;\r
 #endif\r
 \r
 #if defined(JUCE_FIREBASE_MESSAGING_SERVICE_CLASSNAME)\r
@@ -1609,8 +1590,6 @@ struct JuceFirebaseMessagingService
                                                                               LocalRef<jstring> (static_cast<jstring> (error)));\r
     }\r
 };\r
-\r
-JuceFirebaseMessagingService::MessagingService_Class  JuceFirebaseMessagingService::MessagingService;\r
 #endif\r
 \r
 //==============================================================================\r
index 35adf391c1e14687320f9510137ef9af8582ec7a..b4871cd9c5807df7dc7b476bf584a66da92b37df 100644 (file)
@@ -29,7 +29,7 @@ namespace juce
 //==============================================================================\r
 // This byte-code is generated from native/java/com/rmsl/juce/JuceWebView.java with min sdk version 16\r
 // See juce_core/native/java/README.txt on how to generate this byte-code.\r
-static const unsigned char JuceWebView16ByteCode[] =\r
+static const uint8 JuceWebView16ByteCode[] =\r
 {31,139,8,8,150,114,161,94,0,3,74,117,99,101,87,101,98,86,105,101,119,49,54,66,121,116,101,67,111,100,101,46,100,101,120,0,125,\r
 150,93,108,20,85,20,199,207,124,236,78,119,218,110,183,5,74,191,40,109,69,168,72,89,176,162,165,11,88,40,159,101,81,161,88,226,\r
 106,34,211,221,107,59,101,118,102,153,153,109,27,67,16,161,137,134,240,96,4,222,72,140,9,18,35,62,18,195,131,15,4,53,250,226,155,\r
@@ -81,7 +81,7 @@ static const unsigned char JuceWebView16ByteCode[] =
 //==============================================================================\r
 // This byte-code is generated from native/javacore/app/com/rmsl/juce/JuceWebView21.java with min sdk version 21\r
 // See juce_core/native/java/README.txt on how to generate this byte-code.\r
-static const unsigned char JuceWebView21ByteCode[] =\r
+static const uint8 JuceWebView21ByteCode[] =\r
 {31,139,8,8,45,103,161,94,0,3,74,117,99,101,87,101,98,86,105,101,119,50,49,46,100,101,120,0,141,151,93,140,27,87,21,199,207,\r
 204,216,30,219,99,59,182,55,251,145,143,221,110,210,173,178,105,154,186,155,164,52,169,211,106,241,38,219,221,48,41,52,155,108,\r
 138,43,85,154,181,47,235,73,188,51,206,204,120,119,65,162,132,80,148,138,34,148,168,20,181,125,129,135,16,129,4,18,168,125,136,\r
@@ -175,7 +175,8 @@ DECLARE_JNI_CLASS (AndroidCookieManager, "android/webkit/CookieManager")
   METHOD (setBuiltInZoomControls,    "setBuiltInZoomControls",    "(Z)V") \\r
   METHOD (setDisplayZoomControls,    "setDisplayZoomControls",    "(Z)V") \\r
   METHOD (setJavaScriptEnabled,      "setJavaScriptEnabled",      "(Z)V") \\r
-  METHOD (setSupportMultipleWindows, "setSupportMultipleWindows", "(Z)V")\r
+  METHOD (setSupportMultipleWindows, "setSupportMultipleWindows", "(Z)V") \\r
+  METHOD (setUserAgentString,        "setUserAgentString",        "(Ljava/lang/String;)V")\r
 \r
 DECLARE_JNI_CLASS (WebSettings, "android/webkit/WebSettings")\r
 #undef JNI_CLASS_MEMBERS\r
@@ -197,7 +198,7 @@ class WebBrowserComponent::Pimpl    : public AndroidViewComponent,
                                       public AsyncUpdater\r
 {\r
 public:\r
-    Pimpl (WebBrowserComponent& o)\r
+    Pimpl (WebBrowserComponent& o, const String& userAgent)\r
         : owner (o)\r
     {\r
         auto* env = getEnv();\r
@@ -210,6 +211,9 @@ public:
         env->CallVoidMethod (settings, WebSettings.setDisplayZoomControls, false);\r
         env->CallVoidMethod (settings, WebSettings.setSupportMultipleWindows, true);\r
 \r
+        if (userAgent.isNotEmpty())\r
+            env->CallVoidMethod (settings, WebSettings.setUserAgentString, javaString (userAgent).get());\r
+\r
         juceWebChromeClient = GlobalRef (LocalRef<jobject> (env->NewObject (JuceWebChromeClient, JuceWebChromeClient.constructor,\r
                                                                             reinterpret_cast<jlong> (this))));\r
         env->CallVoidMethod ((jobject) getView(), AndroidWebView.setWebChromeClient, juceWebChromeClient.get());\r
@@ -475,82 +479,62 @@ private:
     #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
      METHOD (constructor, "<init>",      "(J)V") \\r
      METHOD (hostDeleted, "hostDeleted", "()V") \\r
-     CALLBACK (webViewReceivedHttpError, "webViewReceivedHttpError", "(JLandroid/webkit/WebView;Landroid/webkit/WebResourceRequest;Landroid/webkit/WebResourceResponse;)V") \\r
-     CALLBACK (webViewPageLoadStarted, "webViewPageLoadStarted", "(JLandroid/webkit/WebView;Ljava/lang/String;)Z") \\r
-     CALLBACK (webViewPageLoadFinished, "webViewPageLoadFinished", "(JLandroid/webkit/WebView;Ljava/lang/String;)V") \\r
-     CALLBACK (webViewReceivedSslError, "webViewReceivedSslError", "(JLandroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V") \\r
+     CALLBACK (generatedCallback<&Pimpl::webViewReceivedHttpError>, "webViewReceivedHttpError", "(JLandroid/webkit/WebView;Landroid/webkit/WebResourceRequest;Landroid/webkit/WebResourceResponse;)V") \\r
+     CALLBACK (generatedCallback<&Pimpl::webViewPageLoadStarted>,   "webViewPageLoadStarted",   "(JLandroid/webkit/WebView;Ljava/lang/String;)Z") \\r
+     CALLBACK (generatedCallback<&Pimpl::webViewPageLoadFinished>,  "webViewPageLoadFinished",  "(JLandroid/webkit/WebView;Ljava/lang/String;)V") \\r
+     CALLBACK (generatedCallback<&Pimpl::webViewReceivedSslError>,  "webViewReceivedSslError",  "(JLandroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V") \\r
 \r
-     DECLARE_JNI_CLASS_WITH_BYTECODE (JuceWebViewClient21, "com/rmsl/juce/JuceWebView21$Client", 21, JuceWebView21ByteCode, sizeof (JuceWebView21ByteCode))\r
+     DECLARE_JNI_CLASS_WITH_BYTECODE (JuceWebViewClient21, "com/rmsl/juce/JuceWebView21$Client", 21, JuceWebView21ByteCode)\r
     #undef JNI_CLASS_MEMBERS\r
 \r
     #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
      METHOD (constructor, "<init>",      "(J)V") \\r
      METHOD (hostDeleted, "hostDeleted", "()V") \\r
-     CALLBACK (webViewPageLoadStarted, "webViewPageLoadStarted", "(JLandroid/webkit/WebView;Ljava/lang/String;)Z") \\r
-     CALLBACK (webViewPageLoadFinished, "webViewPageLoadFinished", "(JLandroid/webkit/WebView;Ljava/lang/String;)V") \\r
-     CALLBACK (webViewReceivedSslError, "webViewReceivedSslError", "(JLandroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V") \\r
+     CALLBACK (generatedCallback<&Pimpl::webViewPageLoadStarted>,   "webViewPageLoadStarted",   "(JLandroid/webkit/WebView;Ljava/lang/String;)Z") \\r
+     CALLBACK (generatedCallback<&Pimpl::webViewPageLoadFinished>,  "webViewPageLoadFinished",  "(JLandroid/webkit/WebView;Ljava/lang/String;)V") \\r
+     CALLBACK (generatedCallback<&Pimpl::webViewReceivedSslError>,  "webViewReceivedSslError",  "(JLandroid/webkit/WebView;Landroid/webkit/SslErrorHandler;Landroid/net/http/SslError;)V") \\r
 \r
-     DECLARE_JNI_CLASS_WITH_BYTECODE (JuceWebViewClient16, "com/rmsl/juce/JuceWebView$Client", 16, JuceWebView16ByteCode, sizeof (JuceWebView16ByteCode))\r
+     DECLARE_JNI_CLASS_WITH_BYTECODE (JuceWebViewClient16, "com/rmsl/juce/JuceWebView$Client", 16, JuceWebView16ByteCode)\r
     #undef JNI_CLASS_MEMBERS\r
 \r
-    static jboolean JNICALL webViewPageLoadStarted (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/, jstring url)\r
+    static jboolean webViewPageLoadStarted (JNIEnv*, Pimpl& t, jstring url)\r
     {\r
-        if (auto* myself = reinterpret_cast<WebBrowserComponent::Pimpl*> (host))\r
-            return myself->handlePageAboutToLoad (juceString (url));\r
-\r
-        return 0;\r
+        return t.handlePageAboutToLoad (juceString (url));\r
     }\r
 \r
-    static void JNICALL webViewPageLoadFinished (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/, jstring url)\r
+    static void webViewPageLoadFinished (JNIEnv*, Pimpl& t, jstring url)\r
     {\r
-        if (auto* myself = reinterpret_cast<WebBrowserComponent::Pimpl*> (host))\r
-            myself->owner.pageFinishedLoading (juceString (url));\r
+        t.owner.pageFinishedLoading (juceString (url));\r
     }\r
 \r
-    static void JNICALL webViewReceivedHttpError (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/, jobject /*request*/, jobject errorResponse)\r
+    static void webViewReceivedSslError (JNIEnv* env, Pimpl& t, jobject sslError)\r
     {\r
-        if (auto* myself = reinterpret_cast<WebBrowserComponent::Pimpl*> (host))\r
-            myself->webReceivedHttpError (errorResponse);\r
-    }\r
-\r
-    static void JNICALL webViewReceivedSslError (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/, jobject /*sslErrorHandler*/, jobject sslError)\r
-    {\r
-        auto* env = getEnv();\r
-\r
-        if (auto* myself = reinterpret_cast<WebBrowserComponent::Pimpl*> (host))\r
-        {\r
-            auto errorString = LocalRef<jstring> ((jstring) env->CallObjectMethod (sslError, SslError.toString));\r
-\r
-            myself->owner.pageLoadHadNetworkError (juceString (errorString));\r
-        }\r
+        const auto errorString = LocalRef<jstring> ((jstring) env->CallObjectMethod (sslError, SslError.toString));\r
+        t.owner.pageLoadHadNetworkError (juceString (errorString));\r
     }\r
 \r
     //==============================================================================\r
     #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
       METHOD (constructor, "<init>",      "(J)V") \\r
-      CALLBACK (webViewCloseWindowRequest,  "webViewCloseWindowRequest",  "(JLandroid/webkit/WebView;)V") \\r
-      CALLBACK (webViewCreateWindowRequest, "webViewCreateWindowRequest", "(JLandroid/webkit/WebView;)V") \\r
+      CALLBACK (generatedCallback<&Pimpl::webViewCloseWindowRequest>,   "webViewCloseWindowRequest",    "(JLandroid/webkit/WebView;)V") \\r
+      CALLBACK (generatedCallback<&Pimpl::webViewCreateWindowRequest>,  "webViewCreateWindowRequest",   "(JLandroid/webkit/WebView;)V") \\r
 \r
     DECLARE_JNI_CLASS (JuceWebChromeClient, "com/rmsl/juce/JuceWebView$ChromeClient")\r
     #undef JNI_CLASS_MEMBERS\r
 \r
-    static void JNICALL webViewCloseWindowRequest (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/)\r
+    static void webViewCloseWindowRequest (JNIEnv*, Pimpl& t, jobject)\r
     {\r
-        if (auto* myself = reinterpret_cast<WebBrowserComponent::Pimpl*> (host))\r
-            myself->owner.windowCloseRequest();\r
+        t.owner.windowCloseRequest();\r
     }\r
 \r
-    static void JNICALL webViewCreateWindowRequest (JNIEnv*, jobject /*activity*/, jlong host, jobject /*webView*/)\r
+    static void webViewCreateWindowRequest (JNIEnv*, Pimpl& t, jobject)\r
     {\r
-        if (auto* myself = reinterpret_cast<WebBrowserComponent::Pimpl*> (host))\r
-            myself->owner.newWindowAttemptingToLoad ({});\r
+        t.owner.newWindowAttemptingToLoad ({});\r
     }\r
 \r
     //==============================================================================\r
-    void webReceivedHttpError (jobject errorResponse)\r
+    static void webViewReceivedHttpError (JNIEnv* env, Pimpl& t, jobject errorResponse)\r
     {\r
-        auto* env = getEnv();\r
-\r
         LocalRef<jclass> responseClass (env->FindClass ("android/webkit/WebResourceResponse"));\r
 \r
         if (responseClass != nullptr)\r
@@ -561,14 +545,14 @@ private:
             {\r
                 auto errorString = LocalRef<jstring> ((jstring) env->CallObjectMethod (errorResponse, method));\r
 \r
-                owner.pageLoadHadNetworkError (juceString (errorString));\r
+                t.owner.pageLoadHadNetworkError (juceString (errorString));\r
                 return;\r
             }\r
         }\r
 \r
         // Should never get here!\r
         jassertfalse;\r
-        owner.pageLoadHadNetworkError ({});\r
+        t.owner.pageLoadHadNetworkError ({});\r
     }\r
 \r
     //==============================================================================\r
@@ -582,19 +566,17 @@ private:
 };\r
 \r
 //==============================================================================\r
-WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)\r
+WebBrowserComponent::WebBrowserComponent (const Options& options)\r
     : blankPageShown (false),\r
-      unloadPageWhenHidden (unloadWhenHidden)\r
+      unloadPageWhenHidden (! options.keepsPageLoadedWhenBrowserIsHidden())\r
 {\r
     setOpaque (true);\r
 \r
-    browser.reset (new Pimpl (*this));\r
+    browser.reset (new Pimpl (*this, options.getUserAgent()));\r
     addAndMakeVisible (browser.get());\r
 }\r
 \r
-WebBrowserComponent::~WebBrowserComponent()\r
-{\r
-}\r
+WebBrowserComponent::~WebBrowserComponent() = default;\r
 \r
 //==============================================================================\r
 void WebBrowserComponent::goToURL (const String& url,\r
@@ -719,7 +701,9 @@ void WebBrowserComponent::clearCookies()
     }\r
 }\r
 \r
-WebBrowserComponent::Pimpl::JuceWebViewClient16_Class   WebBrowserComponent::Pimpl::JuceWebViewClient16;\r
-WebBrowserComponent::Pimpl::JuceWebViewClient21_Class   WebBrowserComponent::Pimpl::JuceWebViewClient21;\r
-WebBrowserComponent::Pimpl::JuceWebChromeClient_Class WebBrowserComponent::Pimpl::JuceWebChromeClient;\r
+bool WebBrowserComponent::areOptionsSupported (const Options& options)\r
+{\r
+    return (options.getBackend() == Options::Backend::defaultBackend);\r
+}\r
+\r
 } // namespace juce\r
index ade2379dbe043d1ac290db6870182ee8f1ce5cc0..d7c85d08240e8966b54ae99710117e5ca519aec1 100644 (file)
@@ -587,7 +587,7 @@ struct PushNotifications::Pimpl
         }\r
     }\r
 \r
-    void removeDeliveredNotification (const String& identifier)\r
+    void removeDeliveredNotification ([[maybe_unused]] const String& identifier)\r
     {\r
         if (@available (iOS 10, *))\r
         {\r
@@ -598,15 +598,13 @@ struct PushNotifications::Pimpl
         }\r
         else\r
         {\r
-            ignoreUnused (identifier);\r
             // Not supported on this platform\r
             jassertfalse;\r
         }\r
     }\r
 \r
-    void setupChannels (const Array<ChannelGroup>& groups, const Array<Channel>& channels)\r
+    void setupChannels ([[maybe_unused]] const Array<ChannelGroup>& groups, [[maybe_unused]] const Array<Channel>& channels)\r
     {\r
-        ignoreUnused (groups, channels);\r
     }\r
 \r
     void getPendingLocalNotifications() const\r
@@ -679,18 +677,16 @@ struct PushNotifications::Pimpl
         return deviceToken;\r
     }\r
 \r
-    void subscribeToTopic (const String& topic)     { ignoreUnused (topic); }\r
-    void unsubscribeFromTopic (const String& topic) { ignoreUnused (topic); }\r
+    void subscribeToTopic ([[maybe_unused]] const String& topic)     {}\r
+    void unsubscribeFromTopic ([[maybe_unused]] const String& topic) {}\r
 \r
-    void sendUpstreamMessage (const String& serverSenderId,\r
-                              const String& collapseKey,\r
-                              const String& messageId,\r
-                              const String& messageType,\r
-                              int timeToLive,\r
-                              const StringPairArray& additionalData)\r
+    void sendUpstreamMessage ([[maybe_unused]] const String& serverSenderId,\r
+                              [[maybe_unused]] const String& collapseKey,\r
+                              [[maybe_unused]] const String& messageId,\r
+                              [[maybe_unused]] const String& messageType,\r
+                              [[maybe_unused]] int timeToLive,\r
+                              [[maybe_unused]] const StringPairArray& additionalData)\r
     {\r
-        ignoreUnused (serverSenderId, collapseKey, messageId, messageType);\r
-        ignoreUnused (timeToLive, additionalData);\r
     }\r
 \r
 private:\r
@@ -719,10 +715,8 @@ private:
         owner.listeners.call ([&] (Listener& l) { l.deviceTokenRefreshed (deviceToken); });\r
     }\r
 \r
-    void failedToRegisterForRemoteNotifications (NSError* error)\r
+    void failedToRegisterForRemoteNotifications ([[maybe_unused]] NSError* error)\r
     {\r
-        ignoreUnused (error);\r
-\r
         deviceToken.clear();\r
     }\r
 \r
@@ -794,15 +788,13 @@ private:
 \r
     JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
 \r
-    void willPresentNotificationWithCompletionHandler (UNNotification* notification,\r
+    void willPresentNotificationWithCompletionHandler ([[maybe_unused]] UNNotification* notification,\r
                                                        void (^completionHandler)(UNNotificationPresentationOptions options))\r
     {\r
         NSUInteger options = NSUInteger ((int)settings.allowBadge << 0\r
                                        | (int)settings.allowSound << 1\r
                                        | (int)settings.allowAlert << 2);\r
 \r
-        ignoreUnused (notification);\r
-\r
         completionHandler (options);\r
     }\r
 \r
index 308694571d3733ac2b599812f59b14bb0eb886fe..6acaada9c391a3c2a91a0283150ef0796e317c2a 100644 (file)
@@ -40,6 +40,9 @@ public:
     JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_settings_set_hardware_acceleration_policy, juce_webkit_settings_set_hardware_acceleration_policy,\r
                                          (WebKitSettings*, int), void)\r
 \r
+    JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_settings_set_user_agent, juce_webkit_settings_set_user_agent,\r
+                                         (WebKitSettings*, const gchar*), void)\r
+\r
     JUCE_GENERATE_FUNCTION_WITH_DEFAULT (webkit_web_view_new_with_settings, juce_webkit_web_view_new_with_settings,\r
                                          (WebKitSettings*), GtkWidget*)\r
 \r
@@ -116,6 +119,10 @@ public:
     JUCE_GENERATE_FUNCTION_WITH_DEFAULT (g_signal_connect_data, juce_g_signal_connect_data,\r
                                          (gpointer, const gchar*, GCallback, gpointer, GClosureNotify, GConnectFlags), gulong)\r
 \r
+    //==============================================================================\r
+    JUCE_GENERATE_FUNCTION_WITH_DEFAULT (gdk_set_allowed_backends, juce_gdk_set_allowed_backends,\r
+                                         (const char*), void)\r
+\r
     //==============================================================================\r
     JUCE_DECLARE_SINGLETON_SINGLETHREADED_MINIMAL (WebKitSymbols)\r
 \r
@@ -164,6 +171,7 @@ private:
         return loadSymbols (webkitLib,\r
                             makeSymbolBinding (juce_webkit_settings_new,                                     "webkit_settings_new"),\r
                             makeSymbolBinding (juce_webkit_settings_set_hardware_acceleration_policy,        "webkit_settings_set_hardware_acceleration_policy"),\r
+                            makeSymbolBinding (juce_webkit_settings_set_user_agent,                          "webkit_settings_set_user_agent"),\r
                             makeSymbolBinding (juce_webkit_web_view_new_with_settings,                       "webkit_web_view_new_with_settings"),\r
                             makeSymbolBinding (juce_webkit_policy_decision_use,                              "webkit_policy_decision_use"),\r
                             makeSymbolBinding (juce_webkit_policy_decision_ignore,                           "webkit_policy_decision_ignore"),\r
@@ -182,18 +190,19 @@ private:
     bool loadGtkSymbols()\r
     {\r
         return loadSymbols (gtkLib,\r
-                            makeSymbolBinding (juce_gtk_init,                "gtk_init"),\r
-                            makeSymbolBinding (juce_gtk_plug_new,            "gtk_plug_new"),\r
-                            makeSymbolBinding (juce_gtk_scrolled_window_new, "gtk_scrolled_window_new"),\r
-                            makeSymbolBinding (juce_gtk_container_add,       "gtk_container_add"),\r
-                            makeSymbolBinding (juce_gtk_widget_show_all,     "gtk_widget_show_all"),\r
-                            makeSymbolBinding (juce_gtk_plug_get_id,         "gtk_plug_get_id"),\r
-                            makeSymbolBinding (juce_gtk_main,                "gtk_main"),\r
-                            makeSymbolBinding (juce_gtk_main_quit,           "gtk_main_quit"),\r
-                            makeSymbolBinding (juce_g_unix_fd_add,           "g_unix_fd_add"),\r
-                            makeSymbolBinding (juce_g_object_ref,            "g_object_ref"),\r
-                            makeSymbolBinding (juce_g_object_unref,          "g_object_unref"),\r
-                            makeSymbolBinding (juce_g_signal_connect_data,   "g_signal_connect_data"));\r
+                            makeSymbolBinding (juce_gtk_init,                 "gtk_init"),\r
+                            makeSymbolBinding (juce_gtk_plug_new,             "gtk_plug_new"),\r
+                            makeSymbolBinding (juce_gtk_scrolled_window_new,  "gtk_scrolled_window_new"),\r
+                            makeSymbolBinding (juce_gtk_container_add,        "gtk_container_add"),\r
+                            makeSymbolBinding (juce_gtk_widget_show_all,      "gtk_widget_show_all"),\r
+                            makeSymbolBinding (juce_gtk_plug_get_id,          "gtk_plug_get_id"),\r
+                            makeSymbolBinding (juce_gtk_main,                 "gtk_main"),\r
+                            makeSymbolBinding (juce_gtk_main_quit,            "gtk_main_quit"),\r
+                            makeSymbolBinding (juce_g_unix_fd_add,            "g_unix_fd_add"),\r
+                            makeSymbolBinding (juce_g_object_ref,             "g_object_ref"),\r
+                            makeSymbolBinding (juce_g_object_unref,           "g_object_unref"),\r
+                            makeSymbolBinding (juce_g_signal_connect_data,    "g_signal_connect_data"),\r
+                            makeSymbolBinding (juce_gdk_set_allowed_backends, "gdk_set_allowed_backends"));\r
     }\r
 \r
     //==============================================================================\r
@@ -339,20 +348,26 @@ class GtkChildProcess : private CommandReceiver::Responder
 {\r
 public:\r
     //==============================================================================\r
-    GtkChildProcess (int inChannel, int outChannelToUse)\r
+    GtkChildProcess (int inChannel, int outChannelToUse, const String& userAgentToUse)\r
         : outChannel (outChannelToUse),\r
-          receiver (this, inChannel)\r
+          receiver (this, inChannel),\r
+          userAgent (userAgentToUse)\r
     {}\r
 \r
     int entry()\r
     {\r
         CommandReceiver::setBlocking (outChannel, true);\r
 \r
+        // webkit2gtk crashes when using the wayland backend embedded into an x11 window\r
+        WebKitSymbols::getInstance()->juce_gdk_set_allowed_backends ("x11");\r
+\r
         WebKitSymbols::getInstance()->juce_gtk_init (nullptr, nullptr);\r
 \r
         auto* settings = WebKitSymbols::getInstance()->juce_webkit_settings_new();\r
         WebKitSymbols::getInstance()->juce_webkit_settings_set_hardware_acceleration_policy (settings,\r
                                                                                              /* WEBKIT_HARDWARE_ACCELERATION_POLICY_NEVER */ 2);\r
+        if (userAgent.isNotEmpty())\r
+            WebKitSymbols::getInstance()->juce_webkit_settings_set_user_agent (settings, userAgent.toRawUTF8());\r
 \r
         auto* plug      = WebKitSymbols::getInstance()->juce_gtk_plug_new (0);\r
         auto* container = WebKitSymbols::getInstance()->juce_gtk_scrolled_window_new (nullptr, nullptr);\r
@@ -540,10 +555,9 @@ public:
             break;\r
         case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:\r
             {\r
-                auto* response = (WebKitNavigationPolicyDecision*) decision;\r
+                [[maybe_unused]] auto* response = (WebKitNavigationPolicyDecision*) decision;\r
 \r
                 // for now just always allow response requests\r
-                ignoreUnused (response);\r
                 WebKitSymbols::getInstance()->juce_webkit_policy_decision_use (decision);\r
                 return true;\r
             }\r
@@ -598,6 +612,7 @@ private:
 \r
     int outChannel = 0;\r
     CommandReceiver receiver;\r
+    String userAgent;\r
     WebKitWebView* webview = nullptr;\r
     Array<WebKitPolicyDecision*> decisions;\r
 };\r
@@ -607,8 +622,8 @@ class WebBrowserComponent::Pimpl  : private Thread,
                                     private CommandReceiver::Responder\r
 {\r
 public:\r
-    Pimpl (WebBrowserComponent& parent)\r
-        : Thread ("Webview"), owner (parent)\r
+    Pimpl (WebBrowserComponent& parent, const String& userAgentToUse)\r
+        : Thread ("Webview"), owner (parent), userAgent (userAgentToUse)\r
     {\r
         webKitIsAvailable = WebKitSymbols::getInstance()->isWebKitAvailable();\r
     }\r
@@ -626,9 +641,8 @@ public:
 \r
         launchChild();\r
 \r
-        auto ret = pipe (threadControl);\r
+        [[maybe_unused]] auto ret = pipe (threadControl);\r
 \r
-        ignoreUnused (ret);\r
         jassert (ret == 0);\r
 \r
         CommandReceiver::setBlocking (inChannel,        true);\r
@@ -756,11 +770,11 @@ private:
     {\r
         int inPipe[2], outPipe[2];\r
 \r
-        auto ret = pipe (inPipe);\r
-        ignoreUnused (ret); jassert (ret == 0);\r
+        [[maybe_unused]] auto ret = pipe (inPipe);\r
+        jassert (ret == 0);\r
 \r
         ret = pipe (outPipe);\r
-        ignoreUnused (ret); jassert (ret == 0);\r
+        jassert (ret == 0);\r
 \r
         auto pid = fork();\r
         if (pid == 0)\r
@@ -768,7 +782,6 @@ private:
             close (inPipe[0]);\r
             close (outPipe[1]);\r
 \r
-            HeapBlock<const char*> argv (5);\r
             StringArray arguments;\r
 \r
             arguments.add (File::getSpecialLocation (File::currentExecutableFile).getFullPathName());\r
@@ -776,15 +789,21 @@ private:
             arguments.add (String (outPipe[0]));\r
             arguments.add (String (inPipe [1]));\r
 \r
-            for (int i = 0; i < arguments.size(); ++i)\r
-                argv[i] = arguments[i].toRawUTF8();\r
+            if (userAgent.isNotEmpty())\r
+                arguments.add (userAgent);\r
 \r
-            argv[4] = nullptr;\r
+            std::vector<const char*> argv;\r
+            argv.reserve (static_cast<std::size_t> (arguments.size() + 1));\r
+\r
+            for (const auto& arg : arguments)\r
+                argv.push_back (arg.toRawUTF8());\r
+\r
+            argv.push_back (nullptr);\r
 \r
             if (JUCEApplicationBase::isStandaloneApp())\r
-                execv (arguments[0].toRawUTF8(), (char**) argv.getData());\r
+                execv (arguments[0].toRawUTF8(), (char**) argv.data());\r
             else\r
-                juce_gtkWebkitMain (4, (const char**) argv.getData());\r
+                juce_gtkWebkitMain (arguments.size(), (const char**) argv.data());\r
 \r
             exit (0);\r
         }\r
@@ -896,6 +915,7 @@ private:
     bool webKitIsAvailable = false;\r
 \r
     WebBrowserComponent& owner;\r
+    String userAgent;\r
     std::unique_ptr<CommandReceiver> receiver;\r
     int childProcess = 0, inChannel = 0, outChannel = 0;\r
     int threadControl[2];\r
@@ -905,9 +925,8 @@ private:
 };\r
 \r
 //==============================================================================\r
-WebBrowserComponent::WebBrowserComponent (const bool unloadWhenHidden)\r
-    : browser (new Pimpl (*this)),\r
-      unloadPageWhenHidden (unloadWhenHidden)\r
+WebBrowserComponent::WebBrowserComponent (const Options& options)\r
+    : browser (new Pimpl (*this, options.getUserAgent()))\r
 {\r
     ignoreUnused (blankPageShown);\r
     ignoreUnused (unloadPageWhenHidden);\r
@@ -1010,13 +1029,19 @@ void WebBrowserComponent::clearCookies()
     jassertfalse;\r
 }\r
 \r
+bool WebBrowserComponent::areOptionsSupported (const Options& options)\r
+{\r
+    return (options.getBackend() == Options::Backend::defaultBackend);\r
+}\r
+\r
 int juce_gtkWebkitMain (int argc, const char* argv[])\r
 {\r
-    if (argc != 4)\r
+    if (argc < 4)\r
         return -1;\r
 \r
     GtkChildProcess child (String (argv[2]).getIntValue(),\r
-                           String (argv[3]).getIntValue());\r
+                           String (argv[3]).getIntValue(),\r
+                           argc >= 5 ? String (argv[4]) : String());\r
 \r
     return child.entry();\r
 }\r
index a56538de159896b39e58e14ba260c77e2cc3baf5..768015277ecc6ad7d9d5fe5ab40ef86c4a212c27 100644 (file)
@@ -73,11 +73,13 @@ public:
     {\r
         SharedKeyWindow (ComponentPeer* peerToUse)\r
             : keyPeer (peerToUse),\r
-              keyProxy (juce_createKeyProxyWindow (keyPeer))\r
+              keyProxy (juce_createKeyProxyWindow (keyPeer)),\r
+              association (peerToUse, keyProxy)\r
         {}\r
 \r
         ~SharedKeyWindow()\r
         {\r
+            association = {};\r
             juce_deleteKeyProxyWindow (keyProxy);\r
 \r
             auto& keyWindows = getKeyWindows();\r
@@ -120,6 +122,7 @@ public:
         //==============================================================================\r
         ComponentPeer* keyPeer;\r
         Window keyProxy;\r
+        ScopedWindowAssociation association;\r
 \r
         static HashMap<ComponentPeer*, SharedKeyWindow*>& getKeyWindows()\r
         {\r
index 014fa7f01324cd447a9aaf3728e3d1e9e20a49db..9dddc12a198edd3f6685fb2daf593d11f7376994 100644 (file)
@@ -85,11 +85,9 @@ namespace
                                                    &cfPlugInInterface,\r
                                                    &score) == kIOReturnSuccess)\r
             {\r
-                HRESULT hr = (*cfPlugInInterface)->QueryInterface (cfPlugInInterface,\r
-                                                                   CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID),\r
-                                                                   device);\r
-\r
-                ignoreUnused (hr);\r
+                [[maybe_unused]] HRESULT hr = (*cfPlugInInterface)->QueryInterface (cfPlugInInterface,\r
+                                                                                    CFUUIDGetUUIDBytes (kIOHIDDeviceInterfaceID),\r
+                                                                                    device);\r
 \r
                 (*cfPlugInInterface)->Release (cfPlugInInterface);\r
             }\r
index 7c85aef6dae3f158a02074d743377e5c5bdd3806..762e747c46164adb7b2a2ab6533b0b8bb99bafba 100644 (file)
@@ -164,6 +164,12 @@ void NSViewComponent::resizeToFitView()
     }\r
 }\r
 \r
+void NSViewComponent::resizeViewToFit()\r
+{\r
+    if (attachment != nullptr)\r
+        static_cast<NSViewAttachment*> (attachment.get())->componentMovedOrResized (true, true);\r
+}\r
+\r
 void NSViewComponent::paint (Graphics&) {}\r
 \r
 void NSViewComponent::alphaChanged()\r
index f35ec878fdbedc35baf050b7f1192fed57efd687..4a06ebb16720c3d5830f9dc4fda13bfc2f4e6c0b 100644 (file)
@@ -33,9 +33,7 @@ namespace PushNotificationsDelegateDetailsOsx
     using Action = PushNotifications::Notification::Action;\r
 \r
     //==============================================================================\r
-    NSUserNotification* juceNotificationToNSUserNotification (const PushNotifications::Notification& n,\r
-                                                              bool isEarlierThanMavericks,\r
-                                                              bool isEarlierThanYosemite)\r
+    static NSUserNotification* juceNotificationToNSUserNotification (const PushNotifications::Notification& n)\r
     {\r
         auto notification = [[NSUserNotification alloc] init];\r
 \r
@@ -78,7 +76,7 @@ namespace PushNotificationsDelegateDetailsOsx
         if (n.actions.size() > 0)\r
             notification.actionButtonTitle = juceStringToNS (n.actions.getReference (0).title);\r
 \r
-        if (! isEarlierThanMavericks)\r
+        if (@available (macOS 10.9, *))\r
         {\r
             notification.identifier = juceStringToNS (n.identifier);\r
 \r
@@ -112,7 +110,7 @@ namespace PushNotificationsDelegateDetailsOsx
 \r
             notification.contentImage = [[NSImage alloc] initWithContentsOfFile: imagePath];\r
 \r
-            if (! isEarlierThanYosemite)\r
+            if (@available (macOS 10.10, *))\r
             {\r
                 if (n.actions.size() > 1)\r
                 {\r
@@ -133,9 +131,7 @@ namespace PushNotificationsDelegateDetailsOsx
     }\r
 \r
     //==============================================================================\r
-    PushNotifications::Notification nsUserNotificationToJuceNotification (NSUserNotification* n,\r
-                                                                          bool isEarlierThanMavericks,\r
-                                                                          bool isEarlierThanYosemite)\r
+    static PushNotifications::Notification nsUserNotificationToJuceNotification (NSUserNotification* n)\r
     {\r
         PushNotifications::Notification notif;\r
 \r
@@ -160,7 +156,7 @@ namespace PushNotificationsDelegateDetailsOsx
         notif.soundToPlay = URL (nsStringToJuce (n.soundName));\r
         notif.properties  = nsDictionaryToVar (n.userInfo);\r
 \r
-        if (! isEarlierThanMavericks)\r
+        if (@available (macOS 10.9, *))\r
         {\r
             notif.identifier = nsStringToJuce (n.identifier);\r
 \r
@@ -175,7 +171,7 @@ namespace PushNotificationsDelegateDetailsOsx
             Action action;\r
             action.title = nsStringToJuce (n.actionButtonTitle);\r
 \r
-            if (! isEarlierThanMavericks)\r
+            if (@available (macOS 10.9, *))\r
             {\r
                 if (n.hasReplyButton)\r
                     action.style = Action::text;\r
@@ -187,7 +183,7 @@ namespace PushNotificationsDelegateDetailsOsx
             actions.add (action);\r
         }\r
 \r
-        if (! isEarlierThanYosemite)\r
+        if (@available (macOS 10.10, *))\r
         {\r
             if (n.additionalActions != nil)\r
             {\r
@@ -206,7 +202,7 @@ namespace PushNotificationsDelegateDetailsOsx
     }\r
 \r
     //==============================================================================\r
-    var getNotificationPropertiesFromDictionaryVar (const var& dictionaryVar)\r
+    static var getNotificationPropertiesFromDictionaryVar (const var& dictionaryVar)\r
     {\r
         auto* dictionaryVarObject = dictionaryVar.getDynamicObject();\r
 \r
@@ -230,7 +226,7 @@ namespace PushNotificationsDelegateDetailsOsx
         return var (propsVarObject.get());\r
     }\r
 \r
-    PushNotifications::Notification nsDictionaryToJuceNotification (NSDictionary* dictionary)\r
+    static PushNotifications::Notification nsDictionaryToJuceNotification (NSDictionary* dictionary)\r
     {\r
         const var dictionaryVar = nsDictionaryToVar (dictionary);\r
 \r
@@ -362,44 +358,48 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
 \r
     void requestPermissionsWithSettings (const PushNotifications::Settings& settingsToUse)\r
     {\r
-        if (isEarlierThanLion)\r
-            return;\r
-\r
-        settings = settingsToUse;\r
+        if (@available (macOS 10.7, *))\r
+        {\r
+            settings = settingsToUse;\r
 \r
-        NSRemoteNotificationType types = NSUInteger ((bool) settings.allowBadge);\r
+            NSRemoteNotificationType types = NSUInteger ((bool) settings.allowBadge);\r
 \r
-        if (isAtLeastMountainLion)\r
-            types |= (NSUInteger) ((bool) settings.allowSound << 1 | (bool) settings.allowAlert << 2);\r
+            if (@available (macOS 10.8, *))\r
+            {\r
+                types |= (NSUInteger) ((settings.allowSound ? NSRemoteNotificationTypeSound : 0)\r
+                                     | (settings.allowAlert ? NSRemoteNotificationTypeAlert : 0));\r
+            }\r
 \r
-        [[NSApplication sharedApplication] registerForRemoteNotificationTypes: types];\r
+            [[NSApplication sharedApplication] registerForRemoteNotificationTypes: types];\r
+        }\r
     }\r
 \r
     void requestSettingsUsed()\r
     {\r
-        if (isEarlierThanLion)\r
+        if (@available (macOS 10.7, *))\r
         {\r
-            // no settings available\r
-            owner.listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); });\r
-            return;\r
-        }\r
+            settings.allowBadge = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeBadge;\r
 \r
-        settings.allowBadge = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeBadge;\r
+            if (@available (macOS 10.8, *))\r
+            {\r
+                settings.allowSound = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeSound;\r
+                settings.allowAlert = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeAlert;\r
+            }\r
 \r
-        if (isAtLeastMountainLion)\r
+            owner.listeners.call ([&] (Listener& l) { l.notificationSettingsReceived (settings); });\r
+        }\r
+        else\r
         {\r
-            settings.allowSound = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeSound;\r
-            settings.allowAlert = [NSApplication sharedApplication].enabledRemoteNotificationTypes & NSRemoteNotificationTypeAlert;\r
+            // no settings available\r
+            owner.listeners.call ([] (Listener& l) { l.notificationSettingsReceived ({}); });\r
         }\r
-\r
-        owner.listeners.call ([&] (Listener& l) { l.notificationSettingsReceived (settings); });\r
     }\r
 \r
     bool areNotificationsEnabled() const { return true; }\r
 \r
     void sendLocalNotification (const Notification& n)\r
     {\r
-        auto* notification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n, isEarlierThanMavericks, isEarlierThanYosemite);\r
+        auto* notification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n);\r
 \r
         [[NSUserNotificationCenter defaultUserNotificationCenter] scheduleNotification: notification];\r
     }\r
@@ -409,7 +409,7 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         Array<PushNotifications::Notification> notifs;\r
 \r
         for (NSUserNotification* n in [NSUserNotificationCenter defaultUserNotificationCenter].deliveredNotifications)\r
-            notifs.add (PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (n, isEarlierThanMavericks, isEarlierThanYosemite));\r
+            notifs.add (PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (n));\r
 \r
         owner.listeners.call ([&] (Listener& l) { l.deliveredNotificationsListReceived (notifs); });\r
     }\r
@@ -424,14 +424,13 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         PushNotifications::Notification n;\r
         n.identifier = identifier;\r
 \r
-        auto nsNotification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n, isEarlierThanMavericks, isEarlierThanYosemite);\r
+        auto nsNotification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n);\r
 \r
         [[NSUserNotificationCenter defaultUserNotificationCenter] removeDeliveredNotification: nsNotification];\r
     }\r
 \r
-    void setupChannels (const Array<ChannelGroup>& groups, const Array<Channel>& channels)\r
+    void setupChannels ([[maybe_unused]] const Array<ChannelGroup>& groups, [[maybe_unused]] const Array<Channel>& channels)\r
     {\r
-        ignoreUnused (groups, channels);\r
     }\r
 \r
     void getPendingLocalNotifications() const\r
@@ -439,7 +438,7 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         Array<PushNotifications::Notification> notifs;\r
 \r
         for (NSUserNotification* n in [NSUserNotificationCenter defaultUserNotificationCenter].scheduledNotifications)\r
-            notifs.add (PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (n, isEarlierThanMavericks, isEarlierThanYosemite));\r
+            notifs.add (PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (n));\r
 \r
         owner.listeners.call ([&] (Listener& l) { l.pendingLocalNotificationsListReceived (notifs); });\r
     }\r
@@ -449,7 +448,7 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         PushNotifications::Notification n;\r
         n.identifier = identifier;\r
 \r
-        auto nsNotification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n, isEarlierThanMavericks, isEarlierThanYosemite);\r
+        auto nsNotification = PushNotificationsDelegateDetailsOsx::juceNotificationToNSUserNotification (n);\r
 \r
         [[NSUserNotificationCenter defaultUserNotificationCenter] removeScheduledNotification: nsNotification];\r
     }\r
@@ -494,9 +493,8 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         owner.listeners.call ([&] (Listener& l) { l.deviceTokenRefreshed (deviceToken); });\r
     }\r
 \r
-    void failedToRegisterForRemoteNotifications (NSError* error) override\r
+    void failedToRegisterForRemoteNotifications ([[maybe_unused]] NSError* error) override\r
     {\r
-        ignoreUnused (error);\r
         deviceToken.clear();\r
     }\r
 \r
@@ -506,14 +504,13 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         owner.listeners.call ([&] (Listener& l) { l.handleNotification (true, n); });\r
     }\r
 \r
-    void didDeliverNotification (NSUserNotification* notification) override\r
+    void didDeliverNotification ([[maybe_unused]] NSUserNotification* notification) override\r
     {\r
-        ignoreUnused (notification);\r
     }\r
 \r
     void didActivateNotification (NSUserNotification* notification) override\r
     {\r
-        auto n = PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (notification, isEarlierThanMavericks, isEarlierThanYosemite);\r
+        auto n = PushNotificationsDelegateDetailsOsx::nsUserNotificationToJuceNotification (notification);\r
 \r
         if (notification.activationType == NSUserNotificationActivationTypeContentsClicked)\r
         {\r
@@ -521,9 +518,14 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
         }\r
         else\r
         {\r
-            auto actionIdentifier = (! isEarlierThanYosemite && notification.additionalActivationAction != nil)\r
-                                        ? nsStringToJuce (notification.additionalActivationAction.identifier)\r
-                                        : nsStringToJuce (notification.actionButtonTitle);\r
+            const auto actionIdentifier = nsStringToJuce ([&]\r
+            {\r
+                if (@available (macOS 10.10, *))\r
+                    if (notification.additionalActivationAction != nil)\r
+                        return notification.additionalActivationAction.identifier;\r
+\r
+                return notification.actionButtonTitle;\r
+            }());\r
 \r
             auto reply = notification.activationType == NSUserNotificationActivationTypeReplied\r
                             ? nsStringToJuce ([notification.response string])\r
@@ -535,28 +537,21 @@ struct PushNotifications::Pimpl : private PushNotificationsDelegate
 \r
     bool shouldPresentNotification (NSUserNotification*) override { return true; }\r
 \r
-    void subscribeToTopic (const String& topic)     { ignoreUnused (topic); }\r
-    void unsubscribeFromTopic (const String& topic) { ignoreUnused (topic); }\r
+    void subscribeToTopic ([[maybe_unused]] const String& topic)     {}\r
+    void unsubscribeFromTopic ([[maybe_unused]] const String& topic) {}\r
 \r
-    void sendUpstreamMessage (const String& serverSenderId,\r
-                              const String& collapseKey,\r
-                              const String& messageId,\r
-                              const String& messageType,\r
-                              int timeToLive,\r
-                              const StringPairArray& additionalData)\r
+    void sendUpstreamMessage ([[maybe_unused]] const String& serverSenderId,\r
+                              [[maybe_unused]] const String& collapseKey,\r
+                              [[maybe_unused]] const String& messageId,\r
+                              [[maybe_unused]] const String& messageType,\r
+                              [[maybe_unused]] int timeToLive,\r
+                              [[maybe_unused]] const StringPairArray& additionalData)\r
     {\r
-        ignoreUnused (serverSenderId, collapseKey, messageId, messageType);\r
-        ignoreUnused (timeToLive, additionalData);\r
     }\r
 \r
 private:\r
     PushNotifications& owner;\r
 \r
-    const bool isEarlierThanLion      = std::floor (NSFoundationVersionNumber) < std::floor (NSFoundationVersionNumber10_7);\r
-    const bool isAtLeastMountainLion  = std::floor (NSFoundationVersionNumber) >= NSFoundationVersionNumber10_7;\r
-    const bool isEarlierThanMavericks = std::floor (NSFoundationVersionNumber) < NSFoundationVersionNumber10_9;\r
-    const bool isEarlierThanYosemite  = std::floor (NSFoundationVersionNumber) <= NSFoundationVersionNumber10_9;\r
-\r
     bool initialised = false;\r
     String deviceToken;\r
 \r
index 8f3c3701bd4f71b9c5beb2f937e50e71bbc4ab80..1d0fef01d9a948a46ae9f8a7f0260932f2d5a58d 100644 (file)
@@ -412,7 +412,7 @@ JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")
 class WebViewImpl  : public WebViewBase\r
 {\r
 public:\r
-    WebViewImpl (WebBrowserComponent* owner)\r
+    WebViewImpl (WebBrowserComponent* owner, const String& userAgent)\r
     {\r
         static WebViewKeyEquivalentResponder<WebView> webviewClass;\r
 \r
@@ -420,6 +420,8 @@ public:
                                                           frameName: nsEmptyString()\r
                                                           groupName: nsEmptyString()]);\r
 \r
+        webView.get().customUserAgent = juceStringToNS (userAgent);\r
+\r
         static DownloadClickDetectorClass cls;\r
         clickListener.reset ([cls.createInstance() init]);\r
         DownloadClickDetectorClass::setOwner (clickListener.get(), owner);\r
@@ -497,22 +499,29 @@ JUCE_END_IGNORE_WARNINGS_GCC_LIKE
 class API_AVAILABLE (macos (10.11)) WKWebViewImpl : public WebViewBase\r
 {\r
 public:\r
-    WKWebViewImpl (WebBrowserComponent* owner)\r
+    WKWebViewImpl (WebBrowserComponent* owner, const String& userAgent)\r
     {\r
-        #if JUCE_MAC\r
-         static WebViewKeyEquivalentResponder<WKWebView> webviewClass;\r
+       #if JUCE_MAC\r
+        static WebViewKeyEquivalentResponder<WKWebView> webviewClass;\r
+\r
+        webView.reset ([webviewClass.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)]);\r
+       #else\r
+        webView.reset ([[WKWebView alloc] initWithFrame: CGRectMake (0, 0, 100.0f, 100.0f)]);\r
+       #endif\r
+\r
+        if (userAgent.isNotEmpty())\r
+            webView.get().customUserAgent = juceStringToNS (userAgent);\r
 \r
-         webView.reset ([webviewClass.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)]);\r
-        #else\r
-         webView.reset ([[WKWebView alloc] initWithFrame: CGRectMake (0, 0, 100.0f, 100.0f)]);\r
-        #endif\r
+        static WebViewDelegateClass cls;\r
+        webViewDelegate.reset ([cls.createInstance() init]);\r
+        WebViewDelegateClass::setOwner (webViewDelegate.get(), owner);\r
 \r
-         static WebViewDelegateClass cls;\r
-         webViewDelegate.reset ([cls.createInstance() init]);\r
-         WebViewDelegateClass::setOwner (webViewDelegate.get(), owner);\r
+        [webView.get() setNavigationDelegate: webViewDelegate.get()];\r
+        [webView.get() setUIDelegate:         webViewDelegate.get()];\r
 \r
-         [webView.get() setNavigationDelegate: webViewDelegate.get()];\r
-         [webView.get() setUIDelegate:         webViewDelegate.get()];\r
+       #if JUCE_DEBUG\r
+        [[[webView.get() configuration] preferences] setValue: @(true) forKey: @"developerExtrasEnabled"];\r
+       #endif\r
     }\r
 \r
     ~WKWebViewImpl() override\r
@@ -572,19 +581,19 @@ class WebBrowserComponent::Pimpl
                                    #endif\r
 {\r
 public:\r
-    Pimpl (WebBrowserComponent* owner)\r
+    Pimpl (WebBrowserComponent* owner, const String& userAgent)\r
     {\r
         if (@available (macOS 10.11, *))\r
-            webView = std::make_unique<WKWebViewImpl> (owner);\r
+            webView = std::make_unique<WKWebViewImpl> (owner, userAgent);\r
        #if JUCE_MAC\r
         else\r
-            webView = std::make_unique<WebViewImpl> (owner);\r
+            webView = std::make_unique<WebViewImpl> (owner, userAgent);\r
        #endif\r
 \r
         setView (webView->getWebView());\r
     }\r
 \r
-    ~Pimpl()\r
+    ~Pimpl() override\r
     {\r
         webView = nullptr;\r
         setView (nil);\r
@@ -608,11 +617,11 @@ private:
 };\r
 \r
 //==============================================================================\r
-WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)\r
-    : unloadPageWhenHidden (unloadWhenHidden)\r
+WebBrowserComponent::WebBrowserComponent (const Options& options)\r
+    : unloadPageWhenHidden (! options.keepsPageLoadedWhenBrowserIsHidden())\r
 {\r
     setOpaque (true);\r
-    browser.reset (new Pimpl (this));\r
+    browser.reset (new Pimpl (this, options.getUserAgent()));\r
     addAndMakeVisible (browser.get());\r
 }\r
 \r
@@ -734,4 +743,10 @@ void WebBrowserComponent::clearCookies()
     [[NSUserDefaults standardUserDefaults] synchronize];\r
 }\r
 \r
+//==============================================================================\r
+bool WebBrowserComponent::areOptionsSupported (const Options& options)\r
+{\r
+    return (options.getBackend() == Options::Backend::defaultBackend);\r
+}\r
+\r
 } // namespace juce\r
index 29593758a70fa18f65ab279226718dc131e1286a..d4d9a45e070bc0fa8c21dd61ce0c9c20d29c16af 100644 (file)
@@ -147,6 +147,12 @@ namespace ActiveXHelpers
         ~JuceIOleClientSite()\r
         {\r
             inplaceSite->Release();\r
+\r
+            if (dispatchEventHandler != nullptr)\r
+            {\r
+                dispatchEventHandler->Release();\r
+                dispatchEventHandler = nullptr;\r
+            }\r
         }\r
 \r
         JUCE_COMRESULT QueryInterface (REFIID type, void** result)\r
@@ -159,6 +165,12 @@ namespace ActiveXHelpers
                 *result = static_cast<IOleInPlaceSite*> (inplaceSite);\r
                 return S_OK;\r
             }\r
+            else if (type == __uuidof(IDispatch) && dispatchEventHandler != nullptr)\r
+            {\r
+                dispatchEventHandler->AddRef();\r
+                *result = dispatchEventHandler;\r
+                return S_OK;\r
+            }\r
 \r
             return ComBaseClassHelper <IOleClientSite>::QueryInterface (type, result);\r
 \r
@@ -180,7 +192,31 @@ namespace ActiveXHelpers
             return S_FALSE;\r
         }\r
 \r
+        void setEventHandler (void* eventHandler)\r
+        {\r
+            IDispatch* newEventHandler = nullptr;\r
+\r
+            if (eventHandler != nullptr)\r
+            {\r
+                JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wlanguage-extension-token")\r
+\r
+                auto iidIDispatch = __uuidof (IDispatch);\r
+\r
+                if (static_cast<IUnknown*>(eventHandler)->QueryInterface (iidIDispatch, (void**) &newEventHandler) != S_OK\r
+                    || newEventHandler == nullptr)\r
+                    return;\r
+\r
+               JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+            }\r
+\r
+            if (dispatchEventHandler != nullptr)\r
+                dispatchEventHandler->Release();\r
+\r
+            dispatchEventHandler = newEventHandler;\r
+        }\r
+\r
         JuceIOleInPlaceSite* inplaceSite;\r
+        IDispatch* dispatchEventHandler = nullptr;\r
     };\r
 \r
     //==============================================================================\r
@@ -251,6 +287,11 @@ public:
 \r
     ~Pimpl() override\r
     {\r
+        // If the wndproc of the ActiveX HWND isn't set back to it's original\r
+        // wndproc, then clientSite will leak when control is released\r
+        if (controlHWND != nullptr)\r
+            SetWindowLongPtr ((HWND) controlHWND, GWLP_WNDPROC, (LONG_PTR) originalWndProc);\r
+\r
         if (control != nullptr)\r
         {\r
             control->Close (OLECLOSE_NOSAVE);\r
@@ -418,7 +459,7 @@ bool ActiveXControlComponent::createControl (const void* controlIID)
 \r
                 if (newControl->control->DoVerb (OLEIVERB_SHOW, nullptr, newControl->clientSite, 0, hwnd, &rect) == S_OK)\r
                 {\r
-                    control.reset (newControl.release());\r
+                    control = std::move (newControl);\r
                     control->controlHWND = ActiveXHelpers::getHWND (this);\r
 \r
                     if (control->controlHWND != nullptr)\r
@@ -485,6 +526,12 @@ intptr_t ActiveXControlComponent::offerEventToActiveXControlStatic (void* ptr)
     return S_FALSE;\r
 }\r
 \r
+void ActiveXControlComponent::setEventHandler (void* eventHandler)\r
+{\r
+    if (control->clientSite != nullptr)\r
+        control->clientSite->setEventHandler (eventHandler);\r
+}\r
+\r
 LRESULT juce_offerEventToActiveXControl (::MSG& msg);\r
 LRESULT juce_offerEventToActiveXControl (::MSG& msg)\r
 {\r
index 04083be6395b9a0cbff2880ea81fbf6d8bd25ce3..7d23c7f0c3b95fbe090c5a00cfa37bf709947a24 100644 (file)
@@ -52,7 +52,9 @@ class Win32WebView   : public InternalWebViewType,
                        public ActiveXControlComponent\r
 {\r
 public:\r
-    Win32WebView (WebBrowserComponent& owner)\r
+    Win32WebView (WebBrowserComponent& parent, const String& userAgentToUse)\r
+        : owner (parent),\r
+          userAgent (userAgentToUse)\r
     {\r
         owner.addAndMakeVisible (this);\r
     }\r
@@ -60,7 +62,10 @@ public:
     ~Win32WebView() override\r
     {\r
         if (connectionPoint != nullptr)\r
+        {\r
             connectionPoint->Unadvise (adviseCookie);\r
+            connectionPoint->Release();\r
+        }\r
 \r
         if (browser != nullptr)\r
             browser->Release();\r
@@ -75,6 +80,7 @@ public:
 \r
         auto iidWebBrowser2              = __uuidof (IWebBrowser2);\r
         auto iidConnectionPointContainer = __uuidof (IConnectionPointContainer);\r
+        auto iidOleControl               = __uuidof (IOleControl);\r
 \r
         browser = (IWebBrowser2*) queryInterface (&iidWebBrowser2);\r
 \r
@@ -84,13 +90,19 @@ public:
 \r
             if (connectionPoint != nullptr)\r
             {\r
-                if (auto* owner = dynamic_cast<WebBrowserComponent*> (Component::getParentComponent()))\r
-                {\r
-                    auto handler = new EventHandler (*owner);\r
-                    connectionPoint->Advise (handler, &adviseCookie);\r
-                    handler->Release();\r
-                }\r
+                auto handler = new EventHandler (*this);\r
+                connectionPoint->Advise (handler, &adviseCookie);\r
+                setEventHandler (handler);\r
+                handler->Release();\r
             }\r
+\r
+            connectionPointContainer->Release();\r
+        }\r
+\r
+        if (auto oleControl = (IOleControl*) queryInterface (&iidOleControl))\r
+        {\r
+            oleControl->OnAmbientPropertyChange (/*DISPID_AMBIENT_USERAGENT*/-5513);\r
+            oleControl->Release();\r
         }\r
 \r
         JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
@@ -101,7 +113,7 @@ public:
         return browser != nullptr;\r
     }\r
 \r
-    void goToURL (const String& url, const StringArray* headers, const MemoryBlock* postData) override\r
+    void goToURL (const String& url, const StringArray* requestedHeaders, const MemoryBlock* postData) override\r
     {\r
         if (browser != nullptr)\r
         {\r
@@ -111,10 +123,18 @@ public:
             VariantInit (&postDataVar);\r
             VariantInit (&headersVar);\r
 \r
-            if (headers != nullptr)\r
+            StringArray headers;\r
+\r
+            if (userAgent.isNotEmpty())\r
+                headers.add("User-Agent: " + userAgent);\r
+\r
+            if (requestedHeaders != nullptr)\r
+                headers.addArray (*requestedHeaders);\r
+\r
+            if (headers.size() > 0)\r
             {\r
                 V_VT (&headersVar) = VT_BSTR;\r
-                V_BSTR (&headersVar) = SysAllocString ((const OLECHAR*) headers->joinIntoString ("\r\n").toWideCharPointer());\r
+                V_BSTR (&headersVar) = SysAllocString ((const OLECHAR*) headers.joinIntoString ("\r\n").toWideCharPointer());\r
             }\r
 \r
             if (postData != nullptr && postData->getSize() > 0)\r
@@ -220,41 +240,51 @@ public:
     }\r
 \r
 private:\r
+    WebBrowserComponent& owner;\r
     IWebBrowser2* browser = nullptr;\r
     IConnectionPoint* connectionPoint = nullptr;\r
     DWORD adviseCookie = 0;\r
+    String userAgent;\r
 \r
     //==============================================================================\r
     struct EventHandler  : public ComBaseClassHelper<IDispatch>,\r
                            public ComponentMovementWatcher\r
     {\r
-        EventHandler (WebBrowserComponent& w)  : ComponentMovementWatcher (&w), owner (w) {}\r
+        EventHandler (Win32WebView& w)  : ComponentMovementWatcher (&w.owner), owner (w) {}\r
 \r
         JUCE_COMRESULT GetTypeInfoCount (UINT*) override                                 { return E_NOTIMPL; }\r
         JUCE_COMRESULT GetTypeInfo (UINT, LCID, ITypeInfo**) override                    { return E_NOTIMPL; }\r
         JUCE_COMRESULT GetIDsOfNames (REFIID, LPOLESTR*, UINT, LCID, DISPID*) override   { return E_NOTIMPL; }\r
 \r
         JUCE_COMRESULT Invoke (DISPID dispIdMember, REFIID /*riid*/, LCID /*lcid*/, WORD /*wFlags*/, DISPPARAMS* pDispParams,\r
-                               VARIANT* /*pVarResult*/, EXCEPINFO* /*pExcepInfo*/, UINT* /*puArgErr*/) override\r
+                               VARIANT* pVarResult, EXCEPINFO* /*pExcepInfo*/, UINT* /*puArgErr*/) override\r
         {\r
+\r
+            if (dispIdMember == /*DISPID_AMBIENT_USERAGENT*/-5513)\r
+            {\r
+                V_VT( pVarResult ) = VT_BSTR;\r
+                V_BSTR( pVarResult ) = SysAllocString ((const OLECHAR*) String(owner.userAgent).toWideCharPointer());;\r
+                return S_OK;\r
+            }\r
+\r
             if (dispIdMember == DISPID_BEFORENAVIGATE2)\r
             {\r
                 *pDispParams->rgvarg->pboolVal\r
-                    = owner.pageAboutToLoad (getStringFromVariant (pDispParams->rgvarg[5].pvarVal)) ? VARIANT_FALSE\r
+                    = owner.owner.pageAboutToLoad (getStringFromVariant (pDispParams->rgvarg[5].pvarVal)) ? VARIANT_FALSE\r
                                                                                                     : VARIANT_TRUE;\r
                 return S_OK;\r
             }\r
 \r
             if (dispIdMember == 273 /*DISPID_NEWWINDOW3*/)\r
             {\r
-                owner.newWindowAttemptingToLoad (pDispParams->rgvarg[0].bstrVal);\r
+                owner.owner.newWindowAttemptingToLoad (pDispParams->rgvarg[0].bstrVal);\r
                 *pDispParams->rgvarg[3].pboolVal = VARIANT_TRUE;\r
                 return S_OK;\r
             }\r
 \r
             if (dispIdMember == DISPID_DOCUMENTCOMPLETE)\r
             {\r
-                owner.pageFinishedLoading (getStringFromVariant (pDispParams->rgvarg[0].pvarVal));\r
+                owner.owner.pageFinishedLoading (getStringFromVariant (pDispParams->rgvarg[0].pvarVal));\r
                 return S_OK;\r
             }\r
 \r
@@ -275,7 +305,7 @@ private:
                     String message (messageBuffer, size);\r
                     LocalFree (messageBuffer);\r
 \r
-                    if (! owner.pageLoadHadNetworkError (message))\r
+                    if (! owner.owner.pageLoadHadNetworkError (message))\r
                         *pDispParams->rgvarg[0].pboolVal = VARIANT_TRUE;\r
                 }\r
 \r
@@ -284,7 +314,7 @@ private:
 \r
             if (dispIdMember == 263 /*DISPID_WINDOWCLOSING*/)\r
             {\r
-                owner.windowCloseRequest();\r
+                owner.owner.windowCloseRequest();\r
 \r
                 // setting this bool tells the browser to ignore the event - we'll handle it.\r
                 if (pDispParams->cArgs > 0 && pDispParams->rgvarg[0].vt == (VT_BYREF | VT_BOOL))\r
@@ -304,7 +334,7 @@ private:
         using ComponentMovementWatcher::componentMovedOrResized;\r
 \r
     private:\r
-        WebBrowserComponent& owner;\r
+        Win32WebView& owner;\r
 \r
         static String getStringFromVariant (VARIANT* v)\r
         {\r
@@ -328,12 +358,15 @@ class WebView2  : public InternalWebViewType,
                   public ComponentMovementWatcher\r
 {\r
 public:\r
-    WebView2 (WebBrowserComponent& o, const WebView2Preferences& prefs)\r
+    WebView2 (WebBrowserComponent& o, const WebBrowserComponent::Options& prefs)\r
          : ComponentMovementWatcher (&o),\r
            owner (o),\r
-           preferences (prefs)\r
+           preferences (prefs.getWinWebView2BackendOptions()),\r
+           userAgent (prefs.getUserAgent())\r
     {\r
-        if (! createWebViewEnvironment())\r
+        if (auto handle = createWebViewHandle (preferences))\r
+            webViewHandle = std::move (*handle);\r
+        else\r
             throw std::runtime_error ("Failed to create the CoreWebView2Environemnt");\r
 \r
         owner.addAndMakeVisible (this);\r
@@ -343,16 +376,13 @@ public:
     {\r
         removeEventHandlers();\r
         closeWebView();\r
-\r
-        if (webView2LoaderHandle != nullptr)\r
-            ::FreeLibrary (webView2LoaderHandle);\r
     }\r
 \r
     void createBrowser() override\r
     {\r
         if (webView == nullptr)\r
         {\r
-            jassert (webViewEnvironment != nullptr);\r
+            jassert (webViewHandle.environment != nullptr);\r
             createWebView();\r
         }\r
     }\r
@@ -432,6 +462,56 @@ public:
         owner.visibilityChanged();\r
     }\r
 \r
+    //==============================================================================\r
+    struct WebViewHandle\r
+    {\r
+        using LibraryRef = std::unique_ptr<typename std::pointer_traits<HMODULE>::element_type, decltype(&::FreeLibrary)>;\r
+        LibraryRef loaderHandle {nullptr, &::FreeLibrary};\r
+        ComSmartPtr<ICoreWebView2Environment> environment;\r
+    };\r
+\r
+    static std::optional<WebViewHandle> createWebViewHandle(const WebBrowserComponent::Options::WinWebView2& options)\r
+    {\r
+        using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR,\r
+                                                                     ICoreWebView2EnvironmentOptions*,\r
+                                                                     ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);\r
+\r
+        auto dllPath = options.getDLLLocation().getFullPathName();\r
+\r
+        if (dllPath.isEmpty())\r
+            dllPath = "WebView2Loader.dll";\r
+\r
+        WebViewHandle result;\r
+\r
+        result.loaderHandle = WebViewHandle::LibraryRef (LoadLibraryA (dllPath.toUTF8()), &::FreeLibrary);\r
+\r
+        if (result.loaderHandle == nullptr)\r
+            return {};\r
+\r
+        auto* createWebViewEnvironmentWithOptions = (CreateWebViewEnvironmentWithOptionsFunc) GetProcAddress (result.loaderHandle.get(),\r
+                                                                                                              "CreateCoreWebView2EnvironmentWithOptions");\r
+        if (createWebViewEnvironmentWithOptions == nullptr)\r
+            return {};\r
+\r
+        auto webViewOptions = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();\r
+        const auto userDataFolder = options.getUserDataFolder().getFullPathName();\r
+\r
+        auto hr = createWebViewEnvironmentWithOptions (nullptr,\r
+                                                       userDataFolder.isNotEmpty() ? userDataFolder.toWideCharPointer() : nullptr,\r
+                                                       webViewOptions.Get(),\r
+            Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(\r
+                [&result] (HRESULT, ICoreWebView2Environment* env) -> HRESULT\r
+                {\r
+                    result.environment = env;\r
+                    return S_OK;\r
+                }).Get());\r
+\r
+        if (! SUCCEEDED (hr))\r
+            return {};\r
+\r
+        return result;\r
+    }\r
+\r
 private:\r
     //==============================================================================\r
     template <class ArgType>\r
@@ -613,50 +693,17 @@ private:
         {\r
             settings->put_IsStatusBarEnabled (! preferences.getIsStatusBarDisabled());\r
             settings->put_IsBuiltInErrorPageEnabled (! preferences.getIsBuiltInErrorPageDisabled());\r
-        }\r
-    }\r
-\r
-    bool createWebViewEnvironment()\r
-    {\r
-        using CreateWebViewEnvironmentWithOptionsFunc = HRESULT (*) (PCWSTR, PCWSTR,\r
-                                                                     ICoreWebView2EnvironmentOptions*,\r
-                                                                     ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler*);\r
-\r
-        auto dllPath = preferences.getDLLLocation().getFullPathName();\r
 \r
-        if (dllPath.isEmpty())\r
-            dllPath = "WebView2Loader.dll";\r
-\r
-        webView2LoaderHandle = LoadLibraryA (dllPath.toUTF8());\r
+            if (userAgent.isNotEmpty())\r
+            {\r
+                ComSmartPtr<ICoreWebView2Settings2> settings2;\r
 \r
-        if (webView2LoaderHandle == nullptr)\r
-            return false;\r
+                settings.QueryInterface (settings2);\r
 \r
-        auto* createWebViewEnvironmentWithOptions = (CreateWebViewEnvironmentWithOptionsFunc) GetProcAddress (webView2LoaderHandle,\r
-                                                                                                              "CreateCoreWebView2EnvironmentWithOptions");\r
-        if (createWebViewEnvironmentWithOptions == nullptr)\r
-        {\r
-            // failed to load WebView2Loader.dll\r
-            jassertfalse;\r
-            return false;\r
+                if (settings2 != nullptr)\r
+                    settings2->put_UserAgent (userAgent.toWideCharPointer());\r
+            }\r
         }\r
-\r
-        auto options = Microsoft::WRL::Make<CoreWebView2EnvironmentOptions>();\r
-        const auto userDataFolder = preferences.getUserDataFolder().getFullPathName();\r
-\r
-        auto hr = createWebViewEnvironmentWithOptions (nullptr,\r
-                                                       userDataFolder.isNotEmpty() ? userDataFolder.toWideCharPointer() : nullptr,\r
-                                                       options.Get(),\r
-            Callback<ICoreWebView2CreateCoreWebView2EnvironmentCompletedHandler>(\r
-                [weakThis = WeakReference<WebView2> { this }] (HRESULT, ICoreWebView2Environment* env) -> HRESULT\r
-                {\r
-                    if (weakThis != nullptr)\r
-                        weakThis->webViewEnvironment = env;\r
-\r
-                    return S_OK;\r
-                }).Get());\r
-\r
-        return SUCCEEDED (hr);\r
     }\r
 \r
     void createWebView()\r
@@ -667,7 +714,7 @@ private:
 \r
             WeakReference<WebView2> weakThis (this);\r
 \r
-            webViewEnvironment->CreateCoreWebView2Controller ((HWND) peer->getNativeHandle(),\r
+            webViewHandle.environment->CreateCoreWebView2Controller ((HWND) peer->getNativeHandle(),\r
                 Callback<ICoreWebView2CreateCoreWebView2ControllerCompletedHandler> (\r
                     [weakThis = WeakReference<WebView2> { this }] (HRESULT, ICoreWebView2Controller* controller) -> HRESULT\r
                     {\r
@@ -706,7 +753,7 @@ private:
             webView = nullptr;\r
         }\r
 \r
-        webViewEnvironment = nullptr;\r
+        webViewHandle.environment = nullptr;\r
     }\r
 \r
     //==============================================================================\r
@@ -732,11 +779,10 @@ private:
 \r
     //==============================================================================\r
     WebBrowserComponent& owner;\r
-    WebView2Preferences preferences;\r
-\r
-    HMODULE webView2LoaderHandle = nullptr;\r
+    WebBrowserComponent::Options::WinWebView2 preferences;\r
+    String userAgent;\r
 \r
-    ComSmartPtr<ICoreWebView2Environment> webViewEnvironment;\r
+    WebViewHandle webViewHandle;\r
     ComSmartPtr<ICoreWebView2Controller> webViewController;\r
     ComSmartPtr<ICoreWebView2> webView;\r
 \r
@@ -769,8 +815,9 @@ class WebBrowserComponent::Pimpl
 {\r
 public:\r
     Pimpl (WebBrowserComponent& owner,\r
-           const WebView2Preferences& preferences,\r
-           bool useWebView2)\r
+           [[maybe_unused]] const Options& preferences,\r
+           bool useWebView2,\r
+           const String& userAgent)\r
     {\r
         if (useWebView2)\r
         {\r
@@ -783,10 +830,8 @@ public:
            #endif\r
         }\r
 \r
-        ignoreUnused (preferences);\r
-\r
         if (internal == nullptr)\r
-            internal.reset (new Win32WebView (owner));\r
+            internal.reset (new Win32WebView (owner, userAgent));\r
     }\r
 \r
     InternalWebViewType& getInternalWebView()\r
@@ -799,15 +844,10 @@ private:
 };\r
 \r
 //==============================================================================\r
-WebBrowserComponent::WebBrowserComponent (bool unloadWhenHidden)\r
-    : browser (new Pimpl (*this, {}, false)),\r
-      unloadPageWhenHidden (unloadWhenHidden)\r
-{\r
-    setOpaque (true);\r
-}\r
-\r
-WebBrowserComponent::WebBrowserComponent (ConstructWithoutPimpl args)\r
-    : unloadPageWhenHidden (args.unloadWhenHidden)\r
+WebBrowserComponent::WebBrowserComponent (const Options& options)\r
+    : browser (new Pimpl (*this, options,\r
+                          options.getBackend() == Options::Backend::webview2, options.getUserAgent())),\r
+      unloadPageWhenHidden (! options.keepsPageLoadedWhenBrowserIsHidden())\r
 {\r
     setOpaque (true);\r
 }\r
@@ -816,13 +856,6 @@ WebBrowserComponent::~WebBrowserComponent()
 {\r
 }\r
 \r
-WindowsWebView2WebBrowserComponent::WindowsWebView2WebBrowserComponent (bool unloadWhenHidden,\r
-                                                                        const WebView2Preferences& preferences)\r
-    : WebBrowserComponent (ConstructWithoutPimpl { unloadWhenHidden })\r
-{\r
-    browser = std::make_unique<Pimpl> (*this, preferences, true);\r
-}\r
-\r
 //==============================================================================\r
 void WebBrowserComponent::goToURL (const String& url,\r
                                    const StringArray* headers,\r
@@ -977,4 +1010,21 @@ void WebBrowserComponent::clearCookies()
     }\r
 }\r
 \r
+//==============================================================================\r
+bool WebBrowserComponent::areOptionsSupported (const Options& options)\r
+{\r
+    if (options.getBackend() == Options::Backend::defaultBackend || options.getBackend() == Options::Backend::ie)\r
+        return true;\r
+\r
+   #if JUCE_USE_WIN_WEBVIEW2\r
+    if (options.getBackend() != Options::Backend::webview2)\r
+        return false;\r
+\r
+    if (auto webView = WebView2::createWebViewHandle (options.getWinWebView2BackendOptions()))\r
+        return true;\r
+   #endif\r
+\r
+    return false;\r
+}\r
+\r
 } // namespace juce\r
index 7f2a1ae0da3cfa2b3a59584715e4619cecbc6ee2..66d7be3f8b21efc5951f56acb458c86a18373e0b 100644 (file)
@@ -163,24 +163,22 @@ static bool checkPeerIsValid (OpenGLContext* context)
     {\r
         if (auto* comp = context->getTargetComponent())\r
         {\r
-            if (auto* peer = comp->getPeer())\r
+            if (auto* peer [[maybe_unused]] = comp->getPeer())\r
             {\r
                #if JUCE_MAC || JUCE_IOS\r
                 if (auto* nsView = (JUCE_IOS_MAC_VIEW*) peer->getNativeHandle())\r
                 {\r
-                    if (auto nsWindow = [nsView window])\r
+                    if ([[maybe_unused]] auto nsWindow = [nsView window])\r
                     {\r
                        #if JUCE_MAC\r
                         return ([nsWindow isVisible]\r
                                   && (! [nsWindow hidesOnDeactivate] || [NSApp isActive]));\r
                        #else\r
-                        ignoreUnused (nsWindow);\r
                         return true;\r
                        #endif\r
                     }\r
                 }\r
                #else\r
-                ignoreUnused (peer);\r
                 return true;\r
                #endif\r
             }\r
@@ -215,7 +213,9 @@ static void checkGLError (const char* file, const int line)
 \r
 static void clearGLError() noexcept\r
 {\r
+   #if JUCE_DEBUG\r
     while (glGetError() != GL_NO_ERROR) {}\r
+   #endif\r
 }\r
 \r
 struct OpenGLTargetSaver\r
@@ -240,6 +240,22 @@ private:
     OpenGLTargetSaver& operator= (const OpenGLTargetSaver&);\r
 };\r
 \r
+static bool contextRequiresTexture2DEnableDisable()\r
+{\r
+   #if JUCE_OPENGL_ES\r
+    return false;\r
+   #else\r
+    clearGLError();\r
+    GLint mask = 0;\r
+    glGetIntegerv (GL_CONTEXT_PROFILE_MASK, &mask);\r
+\r
+    if (glGetError() == GL_INVALID_ENUM)\r
+        return true;\r
+\r
+    return (mask & (GLint) GL_CONTEXT_CORE_PROFILE_BIT) == 0;\r
+   #endif\r
+}\r
+\r
 } // namespace juce\r
 \r
 //==============================================================================\r
@@ -275,6 +291,7 @@ JUCE_IMPL_WGL_EXTENSION_FUNCTION (wglCreateContextAttribsARB)
 #undef JUCE_IMPL_WGL_EXTENSION_FUNCTION\r
 \r
 #elif JUCE_LINUX || JUCE_BSD\r
+ #include <juce_gui_basics/native/x11/juce_linux_ScopedWindowAssociation.h>\r
  #include "native/juce_OpenGL_linux_X11.h"\r
 \r
 #elif JUCE_ANDROID\r
index 8cf05c2728bebd227af702e778b115cdee70c448..fb3f9fd79a0b7324a41de57d6560cb528984e4ac 100644 (file)
 \r
   ID:                 juce_opengl\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE OpenGL classes\r
   description:        Classes for rendering OpenGL in a JUCE window.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_gui_extra\r
   OSXFrameworks:      OpenGL\r
index d6a642c55f7dfd9d1ae3c3ba0c010f788b381b5f..dc1c2aa126c6861ad8035832539730dcc7a649c9 100644 (file)
@@ -103,28 +103,8 @@ static const uint8 javaJuceOpenGLView[] =
 };\r
 \r
 //==============================================================================\r
-struct AndroidGLCallbacks\r
-{\r
-    static void attachedToWindow   (JNIEnv*, jobject, jlong);\r
-    static void detachedFromWindow (JNIEnv*, jobject, jlong);\r
-    static void dispatchDraw       (JNIEnv*, jobject, jlong, jobject);\r
-};\r
-\r
-//==============================================================================\r
-#define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
- METHOD (constructor, "<init>",    "(Landroid/content/Context;J)V") \\r
- METHOD (getParent,   "getParent", "()Landroid/view/ViewParent;") \\r
- METHOD (getHolder,   "getHolder", "()Landroid/view/SurfaceHolder;") \\r
- METHOD (layout,      "layout",    "(IIII)V" ) \\r
- CALLBACK (AndroidGLCallbacks::attachedToWindow,   "onAttchedWindowNative",      "(J)V") \\r
- CALLBACK (AndroidGLCallbacks::detachedFromWindow, "onDetachedFromWindowNative", "(J)V") \\r
- CALLBACK (AndroidGLCallbacks::dispatchDraw,       "onDrawNative",               "(JLandroid/graphics/Canvas;)V")\r
-\r
-DECLARE_JNI_CLASS_WITH_BYTECODE (JuceOpenGLViewSurface, "com/rmsl/juce/JuceOpenGLView", 16, javaJuceOpenGLView, sizeof(javaJuceOpenGLView))\r
-#undef JNI_CLASS_MEMBERS\r
-\r
 //==============================================================================\r
-class OpenGLContext::NativeContext   : private SurfaceHolderCallback\r
+class OpenGLContext::NativeContext : private SurfaceHolderCallback\r
 {\r
 public:\r
     NativeContext (Component& comp,\r
@@ -132,8 +112,7 @@ public:
                    void* /*contextToShareWith*/,\r
                    bool useMultisamplingIn,\r
                    OpenGLVersion)\r
-        : component (comp),\r
-          surface (EGL_NO_SURFACE), context (EGL_NO_CONTEXT)\r
+        : component (comp)\r
     {\r
         auto env = getEnv();\r
 \r
@@ -175,88 +154,45 @@ public:
     }\r
 \r
     //==============================================================================\r
-    bool initialiseOnRenderThread (OpenGLContext& aContext)\r
+    InitResult initialiseOnRenderThread (OpenGLContext& ctx)\r
     {\r
-        jassert (hasInitialised);\r
-\r
-        // has the context already attached?\r
-        jassert (surface == EGL_NO_SURFACE && context == EGL_NO_CONTEXT);\r
-\r
-        auto env = getEnv();\r
-\r
-        ANativeWindow* window = nullptr;\r
-\r
-        LocalRef<jobject> holder (env->CallObjectMethod (surfaceView.get(), JuceOpenGLViewSurface.getHolder));\r
-\r
-        if (holder != nullptr)\r
-        {\r
-            LocalRef<jobject> jSurface (env->CallObjectMethod (holder.get(), AndroidSurfaceHolder.getSurface));\r
-\r
-            if (jSurface != nullptr)\r
-            {\r
-                window = ANativeWindow_fromSurface(env, jSurface.get());\r
-\r
-                // if we didn't succeed the first time, wait 25ms and try again\r
-                if (window == nullptr)\r
-                {\r
-                    Thread::sleep (200);\r
-                    window = ANativeWindow_fromSurface (env, jSurface.get());\r
-                }\r
-            }\r
-        }\r
-\r
-        if (window == nullptr)\r
-        {\r
-            // failed to get a pointer to the native window after second try so bail out\r
-            jassertfalse;\r
-            return false;\r
-        }\r
+        // The "real" initialisation happens when the surface is created. Here, we'll\r
+        // just return true if the initialisation happened successfully, or false if\r
+        // it hasn't happened yet, or was unsuccessful.\r
+        const std::lock_guard lock { nativeHandleMutex };\r
 \r
-        // create the surface\r
-        surface = eglCreateWindowSurface (display, config, window, nullptr);\r
-        jassert (surface != EGL_NO_SURFACE);\r
-\r
-        ANativeWindow_release (window);\r
+        if (! hasInitialised)\r
+            return InitResult::fatal;\r
 \r
-        // create the OpenGL context\r
-        EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };\r
-        context = eglCreateContext (display, config, EGL_NO_CONTEXT, contextAttribs);\r
-        jassert (context != EGL_NO_CONTEXT);\r
+        if (context.get() == EGL_NO_CONTEXT && surface.get() == EGL_NO_SURFACE)\r
+            return InitResult::retry;\r
 \r
-        juceContext = &aContext;\r
-        return true;\r
+        juceContext = &ctx;\r
+        return InitResult::success;\r
     }\r
 \r
     void shutdownOnRenderThread()\r
     {\r
-        jassert (hasInitialised);\r
-\r
-        // is there a context available to detach?\r
-        jassert (surface != EGL_NO_SURFACE && context != EGL_NO_CONTEXT);\r
-\r
-        eglDestroyContext (display, context);\r
-        context = EGL_NO_CONTEXT;\r
-\r
-        eglDestroySurface (display, surface);\r
-        surface = EGL_NO_SURFACE;\r
+        const std::lock_guard lock { nativeHandleMutex };\r
+        juceContext = nullptr;\r
     }\r
 \r
     //==============================================================================\r
     bool makeActive() const noexcept\r
     {\r
-        if (! hasInitialised)\r
-            return false;\r
-\r
-        if (surface == EGL_NO_SURFACE || context == EGL_NO_CONTEXT)\r
-            return false;\r
-\r
-        if (! eglMakeCurrent (display, surface, surface, context))\r
-            return false;\r
+        const std::lock_guard lock { nativeHandleMutex };\r
 \r
-        return true;\r
+        return hasInitialised\r
+            && surface.get() != EGL_NO_SURFACE\r
+            && context.get() != EGL_NO_CONTEXT\r
+            && eglMakeCurrent (display, surface.get(), surface.get(), context.get());\r
     }\r
 \r
-    bool isActive() const noexcept              { return eglGetCurrentContext() == context; }\r
+    bool isActive() const noexcept\r
+    {\r
+        const std::lock_guard lock { nativeHandleMutex };\r
+        return eglGetCurrentContext() == context.get();\r
+    }\r
 \r
     static void deactivateCurrentContext()\r
     {\r
@@ -264,7 +200,7 @@ public:
     }\r
 \r
     //==============================================================================\r
-    void swapBuffers() const noexcept           { eglSwapBuffers (display, surface); }\r
+    void swapBuffers() const noexcept           { eglSwapBuffers (display, surface.get()); }\r
     bool setSwapInterval (const int)            { return false; }\r
     int getSwapInterval() const                 { return 0; }\r
 \r
@@ -290,52 +226,66 @@ public:
 \r
     //==============================================================================\r
     // Android Surface Callbacks:\r
-    void surfaceChanged (LocalRef<jobject> holder, int format, int width, int height) override\r
+    void surfaceChanged ([[maybe_unused]] LocalRef<jobject> holder,\r
+                         [[maybe_unused]] int format,\r
+                         [[maybe_unused]] int width,\r
+                         [[maybe_unused]] int height) override\r
     {\r
-        ignoreUnused (holder, format, width, height);\r
     }\r
 \r
-    void surfaceCreated (LocalRef<jobject> holder) override;\r
-    void surfaceDestroyed (LocalRef<jobject> holder) override;\r
+    void surfaceCreated (LocalRef<jobject>) override;\r
+    void surfaceDestroyed (LocalRef<jobject>) override;\r
 \r
     //==============================================================================\r
-    struct Locker { Locker (NativeContext&) {} };\r
+    struct Locker\r
+    {\r
+        explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}\r
+        const ScopedLock lock;\r
+    };\r
 \r
     Component& component;\r
 \r
 private:\r
-    //==============================================================================\r
-    friend struct AndroidGLCallbacks;\r
+    #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
+     METHOD (constructor, "<init>",    "(Landroid/content/Context;J)V") \\r
+     METHOD (getParent,   "getParent", "()Landroid/view/ViewParent;") \\r
+     METHOD (getHolder,   "getHolder", "()Landroid/view/SurfaceHolder;") \\r
+     METHOD (layout,      "layout",    "(IIII)V" ) \\r
+     CALLBACK (generatedCallback<&NativeContext::attachedToWindow>,   "onAttchedWindowNative",      "(J)V") \\r
+     CALLBACK (generatedCallback<&NativeContext::detachedFromWindow>, "onDetachedFromWindowNative", "(J)V") \\r
+     CALLBACK (generatedCallback<&NativeContext::dispatchDraw>,       "onDrawNative",               "(JLandroid/graphics/Canvas;)V")\r
+\r
+     DECLARE_JNI_CLASS_WITH_BYTECODE (JuceOpenGLViewSurface, "com/rmsl/juce/JuceOpenGLView", 16, javaJuceOpenGLView)\r
+    #undef JNI_CLASS_MEMBERS\r
 \r
-    void attachedToWindow()\r
+    //==============================================================================\r
+    static void attachedToWindow (JNIEnv* env, NativeContext& t)\r
     {\r
-        auto* env = getEnv();\r
-\r
-        LocalRef<jobject> holder (env->CallObjectMethod (surfaceView.get(), JuceOpenGLViewSurface.getHolder));\r
+        LocalRef<jobject> holder (env->CallObjectMethod (t.surfaceView.get(), JuceOpenGLViewSurface.getHolder));\r
 \r
-        if (surfaceHolderCallback == nullptr)\r
-            surfaceHolderCallback = GlobalRef (CreateJavaInterface (this, "android/view/SurfaceHolder$Callback"));\r
+        if (t.surfaceHolderCallback == nullptr)\r
+            t.surfaceHolderCallback = GlobalRef (CreateJavaInterface (&t, "android/view/SurfaceHolder$Callback"));\r
 \r
-        env->CallVoidMethod (holder, AndroidSurfaceHolder.addCallback, surfaceHolderCallback.get());\r
+        env->CallVoidMethod (holder, AndroidSurfaceHolder.addCallback, t.surfaceHolderCallback.get());\r
     }\r
 \r
-    void detachedFromWindow()\r
+    static void detachedFromWindow (JNIEnv* env, NativeContext& t)\r
     {\r
-        if (surfaceHolderCallback != nullptr)\r
+        if (t.surfaceHolderCallback != nullptr)\r
         {\r
-            auto* env = getEnv();\r
+            LocalRef<jobject> holder (env->CallObjectMethod (t.surfaceView.get(), JuceOpenGLViewSurface.getHolder));\r
 \r
-            LocalRef<jobject> holder (env->CallObjectMethod (surfaceView.get(), JuceOpenGLViewSurface.getHolder));\r
-\r
-            env->CallVoidMethod (holder.get(), AndroidSurfaceHolder.removeCallback, surfaceHolderCallback.get());\r
-            surfaceHolderCallback.clear();\r
+            env->CallVoidMethod (holder.get(), AndroidSurfaceHolder.removeCallback, t.surfaceHolderCallback.get());\r
+            t.surfaceHolderCallback.clear();\r
         }\r
     }\r
 \r
-    void dispatchDraw (jobject /*canvas*/)\r
+    static void dispatchDraw (JNIEnv*, NativeContext& t, jobject /*canvas*/)\r
     {\r
-        if (juceContext != nullptr)\r
-            juceContext->triggerRepaint();\r
+        const std::lock_guard lock { t.nativeHandleMutex };\r
+\r
+        if (t.juceContext != nullptr)\r
+            t.juceContext->triggerRepaint();\r
     }\r
 \r
     bool tryChooseConfig (const std::vector<EGLint>& optionalAttribs)\r
@@ -389,15 +339,55 @@ private:
         return false;\r
     }\r
 \r
+    struct NativeWindowReleaser\r
+    {\r
+        void operator() (ANativeWindow* ptr) const { if (ptr != nullptr) ANativeWindow_release (ptr); }\r
+    };\r
+\r
+    std::unique_ptr<ANativeWindow, NativeWindowReleaser> getNativeWindow() const\r
+    {\r
+        auto* env = getEnv();\r
+\r
+        const LocalRef<jobject> holder (env->CallObjectMethod (surfaceView.get(), JuceOpenGLViewSurface.getHolder));\r
+\r
+        if (holder == nullptr)\r
+            return nullptr;\r
+\r
+        const LocalRef<jobject> jSurface (env->CallObjectMethod (holder.get(), AndroidSurfaceHolder.getSurface));\r
+\r
+        if (jSurface == nullptr)\r
+            return nullptr;\r
+\r
+        constexpr auto numAttempts = 2;\r
+\r
+        for (auto i = 0; i < numAttempts; Thread::sleep (200), ++i)\r
+            if (auto* ptr = ANativeWindow_fromSurface (env, jSurface.get()))\r
+                return std::unique_ptr<ANativeWindow, NativeWindowReleaser> { ptr };\r
+\r
+        return nullptr;\r
+    }\r
+\r
     //==============================================================================\r
+    CriticalSection mutex;\r
     bool hasInitialised = false;\r
 \r
     GlobalRef surfaceView;\r
     Rectangle<int> lastBounds;\r
 \r
+    struct SurfaceDestructor\r
+    {\r
+        void operator() (EGLSurface x) const { if (x != EGL_NO_SURFACE) eglDestroySurface (display, x); }\r
+    };\r
+\r
+    struct ContextDestructor\r
+    {\r
+        void operator() (EGLContext x) const { if (x != EGL_NO_CONTEXT) eglDestroyContext (display, x); }\r
+    };\r
+\r
+    mutable std::mutex nativeHandleMutex;\r
     OpenGLContext* juceContext = nullptr;\r
-    EGLSurface surface;\r
-    EGLContext context;\r
+    std::unique_ptr<std::remove_pointer_t<EGLSurface>, SurfaceDestructor> surface { EGL_NO_SURFACE };\r
+    std::unique_ptr<std::remove_pointer_t<EGLContext>, ContextDestructor> context { EGL_NO_CONTEXT };\r
 \r
     GlobalRef surfaceHolderCallback;\r
 \r
@@ -407,24 +397,8 @@ private:
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)\r
 };\r
 \r
-//==============================================================================\r
-void AndroidGLCallbacks::attachedToWindow (JNIEnv*, jobject /*this*/, jlong host)\r
-{\r
-    if (auto* nativeContext = reinterpret_cast<OpenGLContext::NativeContext*> (host))\r
-        nativeContext->attachedToWindow();\r
-}\r
-\r
-void AndroidGLCallbacks::detachedFromWindow (JNIEnv*, jobject /*this*/, jlong host)\r
-{\r
-    if (auto* nativeContext = reinterpret_cast<OpenGLContext::NativeContext*> (host))\r
-        nativeContext->detachedFromWindow();\r
-}\r
-\r
-void AndroidGLCallbacks::dispatchDraw (JNIEnv*, jobject /*this*/, jlong host, jobject canvas)\r
-{\r
-    if (auto* nativeContext = reinterpret_cast<OpenGLContext::NativeContext*> (host))\r
-        nativeContext->dispatchDraw (canvas);\r
-}\r
+EGLDisplay OpenGLContext::NativeContext::display = EGL_NO_DISPLAY;\r
+EGLDisplay OpenGLContext::NativeContext::config;\r
 \r
 //==============================================================================\r
 bool OpenGLHelpers::isContextActive()\r
index c67a19d9987fbe8e292f8fd1aa0ee1d917b30be8..813aa7a6528daa234abeff7a45df5fd1dce574e0 100644 (file)
@@ -72,24 +72,19 @@ public:
 \r
                 [((UIView*) peer->getNativeHandle()) addSubview: view];\r
 \r
-                if (version == openGL3_2 && [[UIDevice currentDevice].systemVersion floatValue] >= 7.0)\r
-                {\r
-                    if (! createContext (kEAGLRenderingAPIOpenGLES3, contextToShare))\r
-                    {\r
-                        releaseContext();\r
-                        createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);\r
-                    }\r
-                }\r
-                else\r
-                {\r
-                    createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);\r
-                }\r
+                const auto shouldUseES3 = version != defaultGLVersion\r
+                                       && [[UIDevice currentDevice].systemVersion floatValue] >= 7.0;\r
+\r
+                const auto gotContext = (shouldUseES3 && createContext (kEAGLRenderingAPIOpenGLES3, contextToShare))\r
+                                     || createContext (kEAGLRenderingAPIOpenGLES2, contextToShare);\r
+\r
+                jassertquiet (gotContext);\r
 \r
                 if (context != nil)\r
                 {\r
                     // I'd prefer to put this stuff in the initialiseOnRenderThread() call, but doing\r
                     // so causes mysterious timing-related failures.\r
-                    [EAGLContext setCurrentContext: context];\r
+                    [EAGLContext setCurrentContext: context.get()];\r
                     gl::loadFunctions();\r
                     createGLBuffers();\r
                     deactivateCurrentContext();\r
@@ -108,12 +103,12 @@ public:
 \r
     ~NativeContext()\r
     {\r
-        releaseContext();\r
+        context.reset();\r
         [view removeFromSuperview];\r
         [view release];\r
     }\r
 \r
-    bool initialiseOnRenderThread (OpenGLContext&)    { return true; }\r
+    InitResult initialiseOnRenderThread (OpenGLContext&)    { return InitResult::success; }\r
 \r
     void shutdownOnRenderThread()\r
     {\r
@@ -123,12 +118,12 @@ public:
     }\r
 \r
     bool createdOk() const noexcept             { return getRawContext() != nullptr; }\r
-    void* getRawContext() const noexcept        { return context; }\r
+    void* getRawContext() const noexcept        { return context.get(); }\r
     GLuint getFrameBufferID() const noexcept    { return useMSAA ? msaaBufferHandle : frameBufferHandle; }\r
 \r
     bool makeActive() const noexcept\r
     {\r
-        if (! [EAGLContext setCurrentContext: context])\r
+        if (! [EAGLContext setCurrentContext: context.get()])\r
             return false;\r
 \r
         glBindFramebuffer (GL_FRAMEBUFFER, useMSAA ? msaaBufferHandle\r
@@ -138,7 +133,7 @@ public:
 \r
     bool isActive() const noexcept\r
     {\r
-        return [EAGLContext currentContext] == context;\r
+        return [EAGLContext currentContext] == context.get();\r
     }\r
 \r
     static void deactivateCurrentContext()\r
@@ -170,7 +165,7 @@ public:
         }\r
 \r
         glBindRenderbuffer (GL_RENDERBUFFER, colorBufferHandle);\r
-        [context presentRenderbuffer: GL_RENDERBUFFER];\r
+        [context.get() presentRenderbuffer: GL_RENDERBUFFER];\r
 \r
         if (needToRebuildBuffers)\r
         {\r
@@ -203,13 +198,18 @@ public:
 \r
     int getSwapInterval() const noexcept    { return swapFrames; }\r
 \r
-    struct Locker { Locker (NativeContext&) {} };\r
+    struct Locker\r
+    {\r
+        explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}\r
+        const ScopedLock lock;\r
+    };\r
 \r
 private:\r
+    CriticalSection mutex;\r
     Component& component;\r
     JuceGLView* view = nil;\r
     CAEAGLLayer* glLayer = nil;\r
-    EAGLContext* context = nil;\r
+    NSUniquePtr<EAGLContext> context;\r
     const OpenGLVersion openGLversion;\r
     const bool useDepthBuffer, useMSAA;\r
 \r
@@ -223,21 +223,16 @@ private:
     bool createContext (EAGLRenderingAPI type, void* contextToShare)\r
     {\r
         jassert (context == nil);\r
-        context = [EAGLContext alloc];\r
+        context.reset ([EAGLContext alloc]);\r
 \r
-        context = contextToShare != nullptr\r
-                    ? [context initWithAPI: type  sharegroup: [(EAGLContext*) contextToShare sharegroup]]\r
-                    : [context initWithAPI: type];\r
+        if (contextToShare != nullptr)\r
+            [context.get() initWithAPI: type  sharegroup: [(EAGLContext*) contextToShare sharegroup]];\r
+        else\r
+            [context.get() initWithAPI: type];\r
 \r
         return context != nil;\r
     }\r
 \r
-    void releaseContext()\r
-    {\r
-        [context release];\r
-        context = nil;\r
-    }\r
-\r
     //==============================================================================\r
     void createGLBuffers()\r
     {\r
@@ -249,8 +244,8 @@ private:
 \r
         glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorBufferHandle);\r
 \r
-        bool ok = [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer];\r
-        jassert (ok); ignoreUnused (ok);\r
+        [[maybe_unused]] bool ok = [context.get() renderbufferStorage: GL_RENDERBUFFER fromDrawable: glLayer];\r
+        jassert (ok);\r
 \r
         GLint width, height;\r
         glGetRenderbufferParameteriv (GL_RENDERBUFFER, GL_RENDERBUFFER_WIDTH, &width);\r
@@ -289,7 +284,7 @@ private:
     void freeGLBuffers()\r
     {\r
         JUCE_CHECK_OPENGL_ERROR\r
-        [context renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];\r
+        [context.get() renderbufferStorage: GL_RENDERBUFFER fromDrawable: nil];\r
 \r
         deleteFrameBuffer (frameBufferHandle);\r
         deleteFrameBuffer (msaaBufferHandle);\r
index cda1c8ab7d195ed60536740394a114851f68a7d2..cd12b414f5003867c34fade8c6914658248e6066 100644 (file)
 namespace juce\r
 {\r
 \r
-extern XContext windowHandleXContext;\r
+struct XFreeDeleter\r
+{\r
+    void operator() (void* ptr) const\r
+    {\r
+        if (ptr != nullptr)\r
+            X11Symbols::getInstance()->xFree (ptr);\r
+    }\r
+};\r
+\r
+template <typename Data>\r
+std::unique_ptr<Data, XFreeDeleter> makeXFreePtr (Data* raw) { return std::unique_ptr<Data, XFreeDeleter> (raw); }\r
 \r
 //==============================================================================\r
 // Defined juce_linux_Windowing.cpp\r
 void juce_LinuxAddRepaintListener (ComponentPeer*, Component* dummy);\r
 void juce_LinuxRemoveRepaintListener (ComponentPeer*, Component* dummy);\r
 \r
+class PeerListener : private ComponentMovementWatcher\r
+{\r
+public:\r
+    PeerListener (Component& comp, Window embeddedWindow)\r
+        : ComponentMovementWatcher (&comp),\r
+          window (embeddedWindow),\r
+          association (comp.getPeer(), window) {}\r
+\r
+private:\r
+    using ComponentMovementWatcher::componentMovedOrResized,\r
+          ComponentMovementWatcher::componentVisibilityChanged;\r
+\r
+    void componentMovedOrResized (bool, bool) override {}\r
+    void componentVisibilityChanged() override {}\r
+\r
+    void componentPeerChanged() override\r
+    {\r
+        // This should not be rewritten as a ternary expression or similar.\r
+        // The old association must be destroyed before the new one is created.\r
+        association = {};\r
+\r
+        if (auto* comp = getComponent())\r
+            association = ScopedWindowAssociation (comp->getPeer(), window);\r
+    }\r
+\r
+    Window window{};\r
+    ScopedWindowAssociation association;\r
+};\r
+\r
 //==============================================================================\r
 class OpenGLContext::NativeContext\r
 {\r
@@ -80,15 +119,15 @@ public:
         jassert (peer != nullptr);\r
 \r
         auto windowH = (Window) peer->getNativeHandle();\r
-        auto colourMap = X11Symbols::getInstance()->xCreateColormap (display, windowH, bestVisual->visual, AllocNone);\r
+        auto visual = glXGetVisualFromFBConfig (display, *bestConfig);\r
+        auto colourMap = X11Symbols::getInstance()->xCreateColormap (display, windowH, visual->visual, AllocNone);\r
 \r
         XSetWindowAttributes swa;\r
         swa.colormap = colourMap;\r
         swa.border_pixel = 0;\r
         swa.event_mask = embeddedWindowEventMask;\r
 \r
-        auto glBounds = component.getTopLevelComponent()\r
-                           ->getLocalArea (&component, component.getLocalBounds());\r
+        auto glBounds = component.getTopLevelComponent()->getLocalArea (&component, component.getLocalBounds());\r
 \r
         glBounds = Desktop::getInstance().getDisplays().logicalToPhysical (glBounds);\r
 \r
@@ -96,13 +135,13 @@ public:
                                                                    glBounds.getX(), glBounds.getY(),\r
                                                                    (unsigned int) jmax (1, glBounds.getWidth()),\r
                                                                    (unsigned int) jmax (1, glBounds.getHeight()),\r
-                                                                   0, bestVisual->depth,\r
+                                                                   0, visual->depth,\r
                                                                    InputOutput,\r
-                                                                   bestVisual->visual,\r
+                                                                   visual->visual,\r
                                                                    CWBorderPixel | CWColormap | CWEventMask,\r
                                                                    &swa);\r
 \r
-        X11Symbols::getInstance()->xSaveContext (display, (XID) embeddedWindow, windowHandleXContext, (XPointer) peer);\r
+        peerListener.emplace (component, embeddedWindow);\r
 \r
         X11Symbols::getInstance()->xMapWindow (display, embeddedWindow);\r
         X11Symbols::getInstance()->xFreeColormap (display, colourMap);\r
@@ -135,19 +174,60 @@ public:
                 }\r
             }\r
         }\r
-\r
-        if (bestVisual != nullptr)\r
-            X11Symbols::getInstance()->xFree (bestVisual);\r
     }\r
 \r
-    bool initialiseOnRenderThread (OpenGLContext& c)\r
+    InitResult initialiseOnRenderThread (OpenGLContext& c)\r
     {\r
         XWindowSystemUtilities::ScopedXLock xLock;\r
-        renderContext = glXCreateContext (display, bestVisual, (GLXContext) contextToShareWith, GL_TRUE);\r
+\r
+        const auto components = [&]() -> Optional<Version>\r
+        {\r
+            switch (c.versionRequired)\r
+            {\r
+                case OpenGLVersion::openGL3_2: return Version { 3, 2 };\r
+                case OpenGLVersion::openGL4_1: return Version { 4, 1 };\r
+                case OpenGLVersion::openGL4_3: return Version { 4, 3 };\r
+\r
+                case OpenGLVersion::defaultGLVersion: break;\r
+            }\r
+\r
+            return {};\r
+        }();\r
+\r
+        if (components.hasValue())\r
+        {\r
+            using GLXCreateContextAttribsARB = GLXContext (*) (Display*, GLXFBConfig, GLXContext, Bool, const int*);\r
+\r
+            if (const auto glXCreateContextAttribsARB = (GLXCreateContextAttribsARB) OpenGLHelpers::getExtensionFunction ("glXCreateContextAttribsARB"))\r
+            {\r
+               #if JUCE_DEBUG\r
+                constexpr auto contextFlags = GLX_CONTEXT_DEBUG_BIT_ARB;\r
+               #else\r
+                constexpr auto contextFlags = 0;\r
+               #endif\r
+\r
+                const int attribs[]\r
+                {\r
+                    GLX_CONTEXT_MAJOR_VERSION_ARB, components->major,\r
+                    GLX_CONTEXT_MINOR_VERSION_ARB, components->minor,\r
+                    GLX_CONTEXT_PROFILE_MASK_ARB,  GLX_CONTEXT_CORE_PROFILE_BIT_ARB,\r
+                    GLX_CONTEXT_FLAGS_ARB,         contextFlags,\r
+                    None\r
+                };\r
+\r
+                renderContext = glXCreateContextAttribsARB (display, *bestConfig, (GLXContext) contextToShareWith, GL_TRUE, attribs);\r
+            }\r
+        }\r
+\r
+        if (renderContext == nullptr)\r
+            renderContext = glXCreateNewContext (display, *bestConfig, GLX_RGBA_TYPE, (GLXContext) contextToShareWith, GL_TRUE);\r
+\r
+        if (renderContext == nullptr)\r
+            return InitResult::fatal;\r
+\r
         c.makeActive();\r
         context = &c;\r
-\r
-        return true;\r
+        return InitResult::success;\r
     }\r
 \r
     void shutdownOnRenderThread()\r
@@ -227,15 +307,19 @@ public:
             context->triggerRepaint();\r
     }\r
 \r
-    struct Locker { Locker (NativeContext&) {} };\r
+    struct Locker\r
+    {\r
+        explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}\r
+        const ScopedLock lock;\r
+    };\r
 \r
 private:\r
     bool tryChooseVisual (const OpenGLPixelFormat& format, const std::vector<GLint>& optionalAttribs)\r
     {\r
         std::vector<GLint> allAttribs\r
         {\r
-            GLX_RGBA,\r
-            GLX_DOUBLEBUFFER,\r
+            GLX_RENDER_TYPE,      GLX_RGBA_BIT,\r
+            GLX_DOUBLEBUFFER,     True,\r
             GLX_RED_SIZE,         format.redBits,\r
             GLX_GREEN_SIZE,       format.greenBits,\r
             GLX_BLUE_SIZE,        format.blueBits,\r
@@ -252,20 +336,24 @@ private:
 \r
         allAttribs.push_back (None);\r
 \r
-        bestVisual = glXChooseVisual (display, X11Symbols::getInstance()->xDefaultScreen (display), allAttribs.data());\r
+        int nElements = 0;\r
+        bestConfig = makeXFreePtr (glXChooseFBConfig (display, X11Symbols::getInstance()->xDefaultScreen (display), allAttribs.data(), &nElements));\r
 \r
-        return bestVisual != nullptr;\r
+        return nElements != 0 && bestConfig != nullptr;\r
     }\r
 \r
     static constexpr int embeddedWindowEventMask = ExposureMask | StructureNotifyMask;\r
 \r
+    CriticalSection mutex;\r
     Component& component;\r
     GLXContext renderContext = {};\r
     Window embeddedWindow = {};\r
 \r
+    std::optional<PeerListener> peerListener;\r
+\r
     int swapFrames = 1;\r
     Rectangle<int> bounds;\r
-    XVisualInfo* bestVisual = nullptr;\r
+    std::unique_ptr<GLXFBConfig, XFreeDeleter> bestConfig;\r
     void* contextToShareWith;\r
 \r
     OpenGLContext* context = nullptr;\r
index f3c21b929ead17a331db5ec4cfd582291ba6860e..4996de7b6629d8e5fa51e259310aecb23947daa1 100644 (file)
@@ -38,10 +38,9 @@ public:
                    OpenGLVersion version)\r
         : owner (component)\r
     {\r
-        NSOpenGLPixelFormatAttribute attribs[64] = { 0 };\r
-        createAttribs (attribs, version, pixFormat, shouldUseMultisampling);\r
+        const auto attribs = createAttribs (version, pixFormat, shouldUseMultisampling);\r
 \r
-        NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs];\r
+        NSOpenGLPixelFormat* format = [[NSOpenGLPixelFormat alloc] initWithAttributes: attribs.data()];\r
 \r
         static MouseForwardingNSOpenGLViewClass cls;\r
         view = [cls.createInstance() initWithFrame: NSMakeRect (0, 0, 100.0f, 100.0f)\r
@@ -75,46 +74,55 @@ public:
         [view release];\r
     }\r
 \r
-    static void createAttribs (NSOpenGLPixelFormatAttribute* attribs, OpenGLVersion version,\r
-                               const OpenGLPixelFormat& pixFormat, bool shouldUseMultisampling)\r
+    static std::vector<NSOpenGLPixelFormatAttribute> createAttribs (OpenGLVersion version,\r
+                                                                    const OpenGLPixelFormat& pixFormat,\r
+                                                                    bool shouldUseMultisampling)\r
     {\r
-        ignoreUnused (version);\r
-        int numAttribs = 0;\r
-\r
-        attribs[numAttribs++] = NSOpenGLPFAOpenGLProfile;\r
-        attribs[numAttribs++] = version >= openGL3_2 ? NSOpenGLProfileVersion3_2Core\r
-                                                     : NSOpenGLProfileVersionLegacy;\r
-\r
-        attribs[numAttribs++] = NSOpenGLPFADoubleBuffer;\r
-        attribs[numAttribs++] = NSOpenGLPFAClosestPolicy;\r
-        attribs[numAttribs++] = NSOpenGLPFANoRecovery;\r
-        attribs[numAttribs++] = NSOpenGLPFAColorSize;\r
-        attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) (pixFormat.redBits + pixFormat.greenBits + pixFormat.blueBits);\r
-        attribs[numAttribs++] = NSOpenGLPFAAlphaSize;\r
-        attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) pixFormat.alphaBits;\r
-        attribs[numAttribs++] = NSOpenGLPFADepthSize;\r
-        attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) pixFormat.depthBufferBits;\r
-        attribs[numAttribs++] = NSOpenGLPFAStencilSize;\r
-        attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) pixFormat.stencilBufferBits;\r
-        attribs[numAttribs++] = NSOpenGLPFAAccumSize;\r
-        attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) (pixFormat.accumulationBufferRedBits + pixFormat.accumulationBufferGreenBits\r
-                                                                   + pixFormat.accumulationBufferBlueBits + pixFormat.accumulationBufferAlphaBits);\r
+        std::vector<NSOpenGLPixelFormatAttribute> attribs\r
+        {\r
+            NSOpenGLPFAOpenGLProfile, [version]\r
+            {\r
+                if (version == openGL3_2)\r
+                    return NSOpenGLProfileVersion3_2Core;\r
+\r
+                if (version != defaultGLVersion)\r
+                    if (@available (macOS 10.10, *))\r
+                        return NSOpenGLProfileVersion4_1Core;\r
+\r
+                return NSOpenGLProfileVersionLegacy;\r
+            }(),\r
+            NSOpenGLPFADoubleBuffer,\r
+            NSOpenGLPFAClosestPolicy,\r
+            NSOpenGLPFANoRecovery,\r
+            NSOpenGLPFAColorSize,   static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.redBits + pixFormat.greenBits + pixFormat.blueBits),\r
+            NSOpenGLPFAAlphaSize,   static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.alphaBits),\r
+            NSOpenGLPFADepthSize,   static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.depthBufferBits),\r
+            NSOpenGLPFAStencilSize, static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.stencilBufferBits),\r
+            NSOpenGLPFAAccumSize,   static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.accumulationBufferRedBits  + pixFormat.accumulationBufferGreenBits\r
+                                                                             + pixFormat.accumulationBufferBlueBits + pixFormat.accumulationBufferAlphaBits)\r
+        };\r
 \r
         if (shouldUseMultisampling)\r
         {\r
-            attribs[numAttribs++] = NSOpenGLPFAMultisample;\r
-            attribs[numAttribs++] = NSOpenGLPFASampleBuffers;\r
-            attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) 1;\r
-            attribs[numAttribs++] = NSOpenGLPFASamples;\r
-            attribs[numAttribs++] = (NSOpenGLPixelFormatAttribute) pixFormat.multisamplingLevel;\r
+            attribs.insert (attribs.cend(),\r
+            {\r
+                NSOpenGLPFAMultisample,\r
+                NSOpenGLPFASampleBuffers,   static_cast<NSOpenGLPixelFormatAttribute> (1),\r
+                NSOpenGLPFASamples,         static_cast<NSOpenGLPixelFormatAttribute> (pixFormat.multisamplingLevel)\r
+            });\r
         }\r
+\r
+        attribs.push_back (0);\r
+\r
+        return attribs;\r
     }\r
 \r
-    bool initialiseOnRenderThread (OpenGLContext&)    { return true; }\r
-    void shutdownOnRenderThread()                     { deactivateCurrentContext(); }\r
+    InitResult initialiseOnRenderThread (OpenGLContext&)  { return InitResult::success; }\r
+    void shutdownOnRenderThread()                         { deactivateCurrentContext(); }\r
 \r
     bool createdOk() const noexcept                   { return getRawContext() != nullptr; }\r
-    void* getRawContext() const noexcept              { return static_cast<void*> (renderContext); }\r
+    NSOpenGLView* getNSView() const noexcept          { return view; }\r
+    NSOpenGLContext* getRawContext() const noexcept   { return renderContext; }\r
     GLuint getFrameBufferID() const noexcept          { return 0; }\r
 \r
     bool makeActive() const noexcept\r
@@ -264,24 +272,17 @@ public:
     //==============================================================================\r
     struct MouseForwardingNSOpenGLViewClass  : public ObjCClass<NSOpenGLView>\r
     {\r
-        MouseForwardingNSOpenGLViewClass()  : ObjCClass<NSOpenGLView> ("JUCEGLView_")\r
+        MouseForwardingNSOpenGLViewClass()  : ObjCClass ("JUCEGLView_")\r
         {\r
-            addMethod (@selector (rightMouseDown:),       rightMouseDown);\r
-            addMethod (@selector (rightMouseUp:),         rightMouseUp);\r
-            addMethod (@selector (acceptsFirstMouse:),    acceptsFirstMouse);\r
-            addMethod (@selector (accessibilityHitTest:), accessibilityHitTest);\r
+            addMethod (@selector (rightMouseDown:),       [] (id self, SEL, NSEvent* ev)     { [[(NSOpenGLView*) self superview] rightMouseDown: ev]; });\r
+            addMethod (@selector (rightMouseUp:),         [] (id self, SEL, NSEvent* ev)     { [[(NSOpenGLView*) self superview] rightMouseUp:   ev]; });\r
+            addMethod (@selector (acceptsFirstMouse:),    [] (id, SEL, NSEvent*) -> BOOL     { return YES; });\r
+            addMethod (@selector (accessibilityHitTest:), [] (id self, SEL, NSPoint p) -> id { return [[(NSOpenGLView*) self superview] accessibilityHitTest: p]; });\r
 \r
             registerClass();\r
         }\r
-\r
-    private:\r
-        static void rightMouseDown (id self, SEL, NSEvent* ev)      { [[(NSOpenGLView*) self superview] rightMouseDown: ev]; }\r
-        static void rightMouseUp   (id self, SEL, NSEvent* ev)      { [[(NSOpenGLView*) self superview] rightMouseUp:   ev]; }\r
-        static BOOL acceptsFirstMouse (id, SEL, NSEvent*)           { return YES; }\r
-        static id accessibilityHitTest (id self, SEL, NSPoint p)    { return [[(NSOpenGLView*) self superview] accessibilityHitTest: p]; }\r
     };\r
 \r
-\r
     JUCE_DECLARE_NON_COPYABLE_WITH_LEAK_DETECTOR (NativeContext)\r
 };\r
 \r
index 12dcab98a29c6e826060e87fadca33526f33db49..db07f7a859a9fb3513aa78a5aa27ae0c4fb86f6f 100644 (file)
@@ -44,13 +44,13 @@ public:
         PIXELFORMATDESCRIPTOR pfd;\r
         initialisePixelFormatDescriptor (pfd, pixelFormat);\r
 \r
-        auto pixFormat = ChoosePixelFormat (dc, &pfd);\r
+        auto pixFormat = ChoosePixelFormat (dc.get(), &pfd);\r
 \r
         if (pixFormat != 0)\r
-            SetPixelFormat (dc, pixFormat, &pfd);\r
+            SetPixelFormat (dc.get(), pixFormat, &pfd);\r
 \r
-        initialiseWGLExtensions (dc);\r
-        renderContext = createRenderContext (version, dc);\r
+        initialiseWGLExtensions (dc.get());\r
+        renderContext.reset (createRenderContext (version, dc.get()));\r
 \r
         if (renderContext != nullptr)\r
         {\r
@@ -62,20 +62,20 @@ public:
             if (wglFormat != pixFormat && wglFormat != 0)\r
             {\r
                 // can't change the pixel format of a window, so need to delete the\r
-                // old one and create a new one..\r
-                releaseDC();\r
+                // old one and create a new one.\r
+                dc.reset();\r
                 nativeWindow = nullptr;\r
                 createNativeWindow (component);\r
 \r
-                if (SetPixelFormat (dc, wglFormat, &pfd))\r
+                if (SetPixelFormat (dc.get(), wglFormat, &pfd))\r
                 {\r
-                    deleteRenderContext();\r
-                    renderContext = createRenderContext (version, dc);\r
+                    renderContext.reset();\r
+                    renderContext.reset (createRenderContext (version, dc.get()));\r
                 }\r
             }\r
 \r
             if (contextToShareWithIn != nullptr)\r
-                wglShareLists ((HGLRC) contextToShareWithIn, renderContext);\r
+                wglShareLists ((HGLRC) contextToShareWithIn, renderContext.get());\r
 \r
             component.getTopLevelComponent()->repaint();\r
             component.repaint();\r
@@ -84,19 +84,19 @@ public:
 \r
     ~NativeContext() override\r
     {\r
-        deleteRenderContext();\r
-        releaseDC();\r
+        renderContext.reset();\r
+        dc.reset();\r
 \r
         if (safeComponent != nullptr)\r
             if (auto* peer = safeComponent->getTopLevelComponent()->getPeer())\r
                 peer->removeScaleFactorListener (this);\r
     }\r
 \r
-    bool initialiseOnRenderThread (OpenGLContext& c)\r
+    InitResult initialiseOnRenderThread (OpenGLContext& c)\r
     {\r
         threadAwarenessSetter = std::make_unique<ScopedThreadDPIAwarenessSetter> (nativeWindow->getNativeHandle());\r
         context = &c;\r
-        return true;\r
+        return InitResult::success;\r
     }\r
 \r
     void shutdownOnRenderThread()\r
@@ -107,9 +107,9 @@ public:
     }\r
 \r
     static void deactivateCurrentContext()  { wglMakeCurrent (nullptr, nullptr); }\r
-    bool makeActive() const noexcept        { return isActive() || wglMakeCurrent (dc, renderContext) != FALSE; }\r
-    bool isActive() const noexcept          { return wglGetCurrentContext() == renderContext; }\r
-    void swapBuffers() const noexcept       { SwapBuffers (dc); }\r
+    bool makeActive() const noexcept        { return isActive() || wglMakeCurrent (dc.get(), renderContext.get()) != FALSE; }\r
+    bool isActive() const noexcept          { return wglGetCurrentContext() == renderContext.get(); }\r
+    void swapBuffers() const noexcept       { SwapBuffers (dc.get()); }\r
 \r
     bool setSwapInterval (int numFramesPerSwap)\r
     {\r
@@ -137,7 +137,7 @@ public:
     }\r
 \r
     bool createdOk() const noexcept                 { return getRawContext() != nullptr; }\r
-    void* getRawContext() const noexcept            { return renderContext; }\r
+    void* getRawContext() const noexcept            { return renderContext.get(); }\r
     unsigned int getFrameBufferID() const noexcept  { return 0; }\r
 \r
     void triggerRepaint()\r
@@ -146,7 +146,11 @@ public:
             context->triggerRepaint();\r
     }\r
 \r
-    struct Locker { Locker (NativeContext&) {} };\r
+    struct Locker\r
+    {\r
+        explicit Locker (NativeContext& ctx) : lock (ctx.mutex) {}\r
+        const ScopedLock lock;\r
+    };\r
 \r
     HWND getNativeHandle()\r
     {\r
@@ -206,13 +210,37 @@ private:
 \r
     static HGLRC createRenderContext (OpenGLVersion version, HDC dcIn)\r
     {\r
-        if (version >= openGL3_2 && wglCreateContextAttribsARB != nullptr)\r
+        const auto components = [&]() -> Optional<Version>\r
+        {\r
+            switch (version)\r
+            {\r
+                case OpenGLVersion::openGL3_2: return Version { 3, 2 };\r
+                case OpenGLVersion::openGL4_1: return Version { 4, 1 };\r
+                case OpenGLVersion::openGL4_3: return Version { 4, 3 };\r
+\r
+                case OpenGLVersion::defaultGLVersion: break;\r
+            }\r
+\r
+            return {};\r
+        }();\r
+\r
+        if (components.hasValue() && wglCreateContextAttribsARB != nullptr)\r
         {\r
+           #if JUCE_DEBUG\r
+            constexpr auto contextFlags = WGL_CONTEXT_DEBUG_BIT_ARB;\r
+            constexpr auto noErrorChecking = GL_FALSE;\r
+           #else\r
+            constexpr auto contextFlags = 0;\r
+            constexpr auto noErrorChecking = GL_TRUE;\r
+           #endif\r
+\r
             const int attribs[] =\r
             {\r
-                WGL_CONTEXT_MAJOR_VERSION_ARB, 3,\r
-                WGL_CONTEXT_MINOR_VERSION_ARB, 2,\r
-                WGL_CONTEXT_PROFILE_MASK_ARB,  WGL_CONTEXT_CORE_PROFILE_BIT_ARB,\r
+                WGL_CONTEXT_MAJOR_VERSION_ARB,   components->major,\r
+                WGL_CONTEXT_MINOR_VERSION_ARB,   components->minor,\r
+                WGL_CONTEXT_PROFILE_MASK_ARB,    WGL_CONTEXT_CORE_PROFILE_BIT_ARB,\r
+                WGL_CONTEXT_FLAGS_ARB,           contextFlags,\r
+                WGL_CONTEXT_OPENGL_NO_ERROR_ARB, noErrorChecking,\r
                 0\r
             };\r
 \r
@@ -271,21 +299,8 @@ private:
         }\r
 \r
         nativeWindow->setVisible (true);\r
-        dc = GetDC ((HWND) nativeWindow->getNativeHandle());\r
-    }\r
-\r
-    void deleteRenderContext()\r
-    {\r
-        if (renderContext != nullptr)\r
-        {\r
-            wglDeleteContext (renderContext);\r
-            renderContext = nullptr;\r
-        }\r
-    }\r
-\r
-    void releaseDC()\r
-    {\r
-        ReleaseDC ((HWND) nativeWindow->getNativeHandle(), dc);\r
+        dc = std::unique_ptr<std::remove_pointer_t<HDC>, DeviceContextDeleter> { GetDC ((HWND) nativeWindow->getNativeHandle()),\r
+                                                                                 DeviceContextDeleter { (HWND) nativeWindow->getNativeHandle() } };\r
     }\r
 \r
     int wglChoosePixelFormatExtension (const OpenGLPixelFormat& pixelFormat) const\r
@@ -330,7 +345,7 @@ private:
             jassert (n <= numElementsInArray (atts));\r
 \r
             UINT formatsCount = 0;\r
-            wglChoosePixelFormatARB (dc, atts, nullptr, 1, &format, &formatsCount);\r
+            wglChoosePixelFormatARB (dc.get(), atts, nullptr, 1, &format, &formatsCount);\r
         }\r
 \r
         return format;\r
@@ -347,12 +362,24 @@ private:
     #undef JUCE_DECLARE_WGL_EXTENSION_FUNCTION\r
 \r
     //==============================================================================\r
+    struct RenderContextDeleter\r
+    {\r
+        void operator() (HGLRC ptr) const { wglDeleteContext (ptr); }\r
+    };\r
+\r
+    struct DeviceContextDeleter\r
+    {\r
+        void operator() (HDC ptr) const { ReleaseDC (hwnd, ptr); }\r
+        HWND hwnd;\r
+    };\r
+\r
+    CriticalSection mutex;\r
     std::unique_ptr<DummyComponent> dummyComponent;\r
     std::unique_ptr<ComponentPeer> nativeWindow;\r
     std::unique_ptr<ScopedThreadDPIAwarenessSetter> threadAwarenessSetter;\r
     Component::SafePointer<Component> safeComponent;\r
-    HGLRC renderContext;\r
-    HDC dc;\r
+    std::unique_ptr<std::remove_pointer_t<HGLRC>, RenderContextDeleter> renderContext;\r
+    std::unique_ptr<std::remove_pointer_t<HDC>, DeviceContextDeleter> dc;\r
     OpenGLContext* context = nullptr;\r
     double nativeScaleFactor = 1.0;\r
 \r
index 909cda6e18fa32058ada46d35a49e01ed0199fb3..af3a354fd7e4f1156f788864a309461e234b8843 100644 (file)
   ==============================================================================\r
 */\r
 \r
+#if JUCE_MAC\r
+ #include <juce_gui_basics/native/juce_mac_PerScreenDisplayLinks.h>\r
+#endif\r
+\r
 namespace juce\r
 {\r
 \r
@@ -88,9 +92,11 @@ static bool contextHasTextureNpotFeature()
 }\r
 \r
 //==============================================================================\r
-class OpenGLContext::CachedImage  : public CachedComponentImage,\r
-                                    private ThreadPoolJob\r
+class OpenGLContext::CachedImage  : public CachedComponentImage\r
 {\r
+    template <typename T, typename U>\r
+    static constexpr bool isFlagSet (const T& t, const U& u) { return (t & u) != 0; }\r
+\r
     struct AreaAndScale\r
     {\r
         Rectangle<int> area;\r
@@ -132,8 +138,7 @@ class OpenGLContext::CachedImage  : public CachedComponentImage,
 public:\r
     CachedImage (OpenGLContext& c, Component& comp,\r
                  const OpenGLPixelFormat& pixFormat, void* contextToShare)\r
-        : ThreadPoolJob ("OpenGL Rendering"),\r
-          context (c),\r
+        : context (c),\r
           component (comp)\r
     {\r
         nativeContext.reset (new NativeContext (component, pixFormat, contextToShare,\r
@@ -143,6 +148,8 @@ public:
             context.nativeContext = nativeContext.get();\r
         else\r
             nativeContext.reset();\r
+\r
+        refreshDisplayLinkConnection();\r
     }\r
 \r
     ~CachedImage() override\r
@@ -154,67 +161,61 @@ public:
     void start()\r
     {\r
         if (nativeContext != nullptr)\r
-        {\r
-           #if JUCE_MAC\r
-            cvDisplayLinkWrapper = std::make_unique<CVDisplayLinkWrapper> (*this);\r
-            cvDisplayLinkWrapper->updateActiveDisplay();\r
-           #endif\r
-\r
-            renderThread = std::make_unique<ThreadPool> (1);\r
             resume();\r
-        }\r
     }\r
 \r
     void stop()\r
     {\r
-        if (renderThread != nullptr)\r
-        {\r
-            // make sure everything has finished executing\r
-            destroying = true;\r
-\r
-            if (workQueue.size() > 0)\r
-            {\r
-                if (! renderThread->contains (this))\r
-                    resume();\r
+        // make sure everything has finished executing\r
+        state |= StateFlags::pendingDestruction;\r
 \r
-                while (workQueue.size() != 0)\r
-                    Thread::sleep (20);\r
-            }\r
+        if (workQueue.size() > 0)\r
+        {\r
+            if (! renderThread->contains (this))\r
+                resume();\r
 \r
-            pause();\r
-            renderThread.reset();\r
+            while (workQueue.size() != 0)\r
+                Thread::sleep (20);\r
         }\r
 \r
-       #if JUCE_MAC\r
-        cvDisplayLinkWrapper = nullptr;\r
-       #endif\r
-\r
-        hasInitialised = false;\r
+        pause();\r
     }\r
 \r
     //==============================================================================\r
     void pause()\r
     {\r
-        signalJobShouldExit();\r
-        messageManagerLock.abort();\r
+        renderThread->remove (this);\r
 \r
-        if (renderThread != nullptr)\r
+        if ((state.fetch_and (~StateFlags::initialised) & StateFlags::initialised) != 0)\r
         {\r
-            repaintEvent.signal();\r
-            renderThread->removeJob (this, true, -1);\r
+            context.makeActive();\r
+            shutdownOnThread();\r
+            OpenGLContext::deactivateCurrentContext();\r
         }\r
     }\r
 \r
     void resume()\r
     {\r
-        if (renderThread != nullptr)\r
-            renderThread->addJob (this, false);\r
+        renderThread->add (this);\r
     }\r
 \r
     //==============================================================================\r
     void paint (Graphics&) override\r
     {\r
-        updateViewportSize (false);\r
+        if (MessageManager::getInstance()->isThisTheMessageThread())\r
+        {\r
+            updateViewportSize();\r
+        }\r
+        else\r
+        {\r
+            // If you hit this assertion, it's because paint has been called from a thread other\r
+            // than the message thread. This commonly happens when nesting OpenGL contexts, because\r
+            // the 'outer' OpenGL renderer will attempt to call paint on the 'inner' context's\r
+            // component from the OpenGL thread.\r
+            // Nesting OpenGL contexts is not directly supported, however there is a workaround:\r
+            // https://forum.juce.com/t/opengl-how-do-3d-with-custom-shaders-and-2d-with-juce-paint-methods-work-together/28026/7\r
+            jassertfalse;\r
+        }\r
     }\r
 \r
     bool invalidateAll() override\r
@@ -238,8 +239,8 @@ public:
 \r
     void triggerRepaint()\r
     {\r
-        needsUpdate = 1;\r
-        repaintEvent.signal();\r
+        state |= (StateFlags::pendingRender | StateFlags::paintComponents);\r
+        renderThread->triggerRepaint();\r
     }\r
 \r
     //==============================================================================\r
@@ -282,89 +283,154 @@ public:
         JUCE_CHECK_OPENGL_ERROR\r
     }\r
 \r
-    bool renderFrame()\r
+    struct ScopedContextActivator\r
     {\r
-        MessageManager::Lock::ScopedTryLockType mmLock (messageManagerLock, false);\r
+        bool activate (OpenGLContext& ctx)\r
+        {\r
+            if (! active)\r
+                active = ctx.makeActive();\r
 \r
-        auto isUpdatingTestValue = true;\r
-        auto isUpdating = needsUpdate.compare_exchange_strong (isUpdatingTestValue, false);\r
+            return active;\r
+        }\r
 \r
-        if (context.renderComponents && isUpdating)\r
+        ~ScopedContextActivator()\r
         {\r
-            // This avoids hogging the message thread when doing intensive rendering.\r
-            if (lastMMLockReleaseTime + 1 >= Time::getMillisecondCounter())\r
-                Thread::sleep (2);\r
+            if (active)\r
+                OpenGLContext::deactivateCurrentContext();\r
+        }\r
 \r
-            while (! shouldExit())\r
-            {\r
-                doWorkWhileWaitingForLock (false);\r
+    private:\r
+        bool active = false;\r
+    };\r
 \r
-                if (mmLock.retryLock())\r
-                    break;\r
-            }\r
+    enum class RenderStatus\r
+    {\r
+        nominal,\r
+        messageThreadAborted,\r
+        noWork,\r
+    };\r
 \r
-            if (shouldExit())\r
-                return false;\r
+    RenderStatus renderFrame (MessageManager::Lock& mmLock)\r
+    {\r
+       if (! isFlagSet (state, StateFlags::initialised))\r
+       {\r
+            switch (initialiseOnThread())\r
+            {\r
+                case InitResult::fatal:\r
+                case InitResult::retry: return RenderStatus::noWork;\r
+                case InitResult::success: break;\r
+            }\r
         }\r
 \r
-        if (! context.makeActive())\r
-            return false;\r
+        state |= StateFlags::initialised;\r
 \r
-        NativeContext::Locker locker (*nativeContext);\r
+       #if JUCE_IOS\r
+        if (backgroundProcessCheck.isBackgroundProcess())\r
+            return RenderStatus::noWork;\r
+       #endif\r
 \r
-        JUCE_CHECK_OPENGL_ERROR\r
+        std::optional<MessageManager::Lock::ScopedTryLockType> scopedLock;\r
+        ScopedContextActivator contextActivator;\r
 \r
-        doWorkWhileWaitingForLock (true);\r
+        const auto stateToUse = state.fetch_and (StateFlags::persistent);\r
 \r
-        const auto currentAreaAndScale = areaAndScale.get();\r
-        const auto viewportArea = currentAreaAndScale.area;\r
+       #if JUCE_MAC\r
+        // On macOS, we use a display link callback to trigger repaints, rather than\r
+        // letting them run at full throttle\r
+        const auto noAutomaticRepaint = true;\r
+       #else\r
+        const auto noAutomaticRepaint = ! context.continuousRepaint;\r
+       #endif\r
 \r
-        if (context.renderer != nullptr)\r
+        if (! isFlagSet (stateToUse, StateFlags::pendingRender) && noAutomaticRepaint)\r
+            return RenderStatus::noWork;\r
+\r
+        const auto isUpdating = isFlagSet (stateToUse, StateFlags::paintComponents);\r
+\r
+        if (context.renderComponents && isUpdating)\r
         {\r
-            glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());\r
-            context.currentRenderScale = currentAreaAndScale.scale;\r
-            context.renderer->renderOpenGL();\r
-            clearGLError();\r
+            bool abortScope = false;\r
+            // If we early-exit here, we need to restore these flags so that the render is\r
+            // attempted again in the next time slice.\r
+            const ScopeGuard scope { [&] { if (! abortScope) state |= stateToUse; } };\r
 \r
-            bindVertexArray();\r
+            // This avoids hogging the message thread when doing intensive rendering.\r
+            std::this_thread::sleep_until (lastMMLockReleaseTime + std::chrono::milliseconds { 2 });\r
+\r
+            if (renderThread->isListChanging())\r
+                return RenderStatus::messageThreadAborted;\r
+\r
+            doWorkWhileWaitingForLock (contextActivator);\r
+\r
+            scopedLock.emplace (mmLock);\r
+\r
+            // If we can't get the lock here, it's probably because a context has been removed\r
+            // on the main thread.\r
+            // We return, just in case this renderer needs to be removed from the rendering thread.\r
+            // If another renderer is being removed instead, then we should be able to get the lock\r
+            // next time round.\r
+            if (! scopedLock->isLocked())\r
+                return RenderStatus::messageThreadAborted;\r
+\r
+            abortScope = true;\r
         }\r
 \r
-        if (context.renderComponents)\r
+        if (! contextActivator.activate (context))\r
+            return RenderStatus::noWork;\r
+\r
         {\r
-            if (isUpdating)\r
-            {\r
-                paintComponent (currentAreaAndScale);\r
+            NativeContext::Locker locker (*nativeContext);\r
 \r
-                if (! hasInitialised)\r
-                    return false;\r
+            JUCE_CHECK_OPENGL_ERROR\r
 \r
-                messageManagerLock.exit();\r
-                lastMMLockReleaseTime = Time::getMillisecondCounter();\r
+            doWorkWhileWaitingForLock (contextActivator);\r
+\r
+            const auto currentAreaAndScale = areaAndScale.get();\r
+            const auto viewportArea = currentAreaAndScale.area;\r
+\r
+            if (context.renderer != nullptr)\r
+            {\r
+                glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());\r
+                context.currentRenderScale = currentAreaAndScale.scale;\r
+                context.renderer->renderOpenGL();\r
+                clearGLError();\r
+\r
+                bindVertexArray();\r
             }\r
 \r
-            glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());\r
-            drawComponentBuffer();\r
-        }\r
+            if (context.renderComponents)\r
+            {\r
+                if (isUpdating)\r
+                {\r
+                    paintComponent (currentAreaAndScale);\r
 \r
-        context.swapBuffers();\r
+                    if (! isFlagSet (state, StateFlags::initialised))\r
+                        return RenderStatus::noWork;\r
 \r
-        OpenGLContext::deactivateCurrentContext();\r
-        return true;\r
+                    scopedLock.reset();\r
+                    lastMMLockReleaseTime = std::chrono::steady_clock::now();\r
+                }\r
+\r
+                glViewport (0, 0, viewportArea.getWidth(), viewportArea.getHeight());\r
+                drawComponentBuffer();\r
+            }\r
+        }\r
+\r
+        nativeContext->swapBuffers();\r
+        return RenderStatus::nominal;\r
     }\r
 \r
-    void updateViewportSize (bool canTriggerUpdate)\r
+    void updateViewportSize()\r
     {\r
         JUCE_ASSERT_MESSAGE_THREAD\r
 \r
         if (auto* peer = component.getPeer())\r
         {\r
            #if JUCE_MAC\r
+            updateScreen();\r
+\r
             const auto displayScale = Desktop::getInstance().getGlobalScaleFactor() * [this]\r
             {\r
-                if (auto* wrapper = cvDisplayLinkWrapper.get())\r
-                    if (wrapper->updateActiveDisplay())\r
-                        nativeContext->setNominalVideoRefreshPeriodS (wrapper->getNominalVideoRefreshPeriodS());\r
-\r
                 if (auto* view = getCurrentView())\r
                 {\r
                     if ([view respondsToSelector: @selector (backingScaleFactor)])\r
@@ -377,20 +443,25 @@ public:
                 return areaAndScale.get().scale;\r
             }();\r
            #else\r
-            const auto displayScale = Desktop::getInstance().getDisplays().getDisplayForRect (component.getTopLevelComponent()->getScreenBounds())->scale;\r
+            const auto displayScale = Desktop::getInstance().getDisplays()\r
+                                                            .getDisplayForRect (component.getTopLevelComponent()\r
+                                                                                        ->getScreenBounds())\r
+                                                           ->scale;\r
            #endif\r
 \r
-            auto localBounds = component.getLocalBounds();\r
-            auto newArea = peer->getComponent().getLocalArea (&component, localBounds).withZeroOrigin() * displayScale;\r
+            const auto localBounds = component.getLocalBounds();\r
+            const auto newArea = peer->getComponent().getLocalArea (&component, localBounds).withZeroOrigin() * displayScale;\r
 \r
            #if JUCE_WINDOWS && JUCE_WIN_PER_MONITOR_DPI_AWARE\r
-            auto newScale = getScaleFactorForWindow (nativeContext->getNativeHandle());\r
-            auto desktopScale = Desktop::getInstance().getGlobalScaleFactor();\r
-\r
-            if (! approximatelyEqual (1.0f, desktopScale))\r
-                newScale *= desktopScale;\r
+            // Some hosts (Pro Tools 2022.7) do not take the current DPI into account when sizing\r
+            // plugin editor windows. Instead of querying the OS for the DPI of the editor window,\r
+            // we approximate based on the physical size of the window that was actually provided\r
+            // for the context to draw into. This may break if the OpenGL context's component is\r
+            // scaled differently in its width and height - but in this case, a single scale factor\r
+            // isn't that helpful anyway.\r
+            const auto newScale = (float) newArea.getWidth() / (float) localBounds.getWidth();\r
            #else\r
-            auto newScale = displayScale;\r
+            const auto newScale = (float) displayScale;\r
            #endif\r
 \r
             areaAndScale.set ({ newArea, newScale }, [&]\r
@@ -400,9 +471,7 @@ public:
                                                     (float) newArea.getHeight() / (float) localBounds.getHeight());\r
 \r
                 nativeContext->updateWindowPosition (peer->getAreaCoveredBy (component));\r
-\r
-                if (canTriggerUpdate)\r
-                    invalidateAll();\r
+                invalidateAll();\r
             });\r
         }\r
     }\r
@@ -420,7 +489,7 @@ public:
 \r
         if (lastScreenBounds != screenBounds)\r
         {\r
-            updateViewportSize (true);\r
+            updateViewportSize();\r
             lastScreenBounds = screenBounds;\r
         }\r
     }\r
@@ -461,10 +530,8 @@ public:
 \r
     void drawComponentBuffer()\r
     {\r
-       #if ! JUCE_ANDROID\r
-        glEnable (GL_TEXTURE_2D);\r
-        clearGLError();\r
-       #endif\r
+        if (contextRequiresTexture2DEnableDisable())\r
+            glEnable (GL_TEXTURE_2D);\r
 \r
        #if JUCE_WINDOWS\r
         // some stupidly old drivers are missing this function, so try to at least avoid a crash here,\r
@@ -473,7 +540,9 @@ public:
         jassert (context.extensions.glActiveTexture != nullptr);\r
         if (context.extensions.glActiveTexture != nullptr)\r
        #endif\r
+        {\r
             context.extensions.glActiveTexture (GL_TEXTURE0);\r
+        }\r
 \r
         glBindTexture (GL_TEXTURE_2D, cachedImageFrameBuffer.getTextureID());\r
         bindVertexArray();\r
@@ -523,80 +592,22 @@ public:
 \r
     void handleResize()\r
     {\r
-        updateViewportSize (true);\r
+        updateViewportSize();\r
 \r
        #if JUCE_MAC\r
-        if (hasInitialised)\r
+        if (isFlagSet (state, StateFlags::initialised))\r
         {\r
             [nativeContext->view update];\r
-            renderFrame();\r
+\r
+            // We're already on the message thread, no need to lock it again.\r
+            MessageManager::Lock mml;\r
+            renderFrame (mml);\r
         }\r
        #endif\r
     }\r
 \r
     //==============================================================================\r
-    JobStatus runJob() override\r
-    {\r
-        {\r
-            // Allow the message thread to finish setting-up the context before using it.\r
-            MessageManager::Lock::ScopedTryLockType mmLock (messageManagerLock, false);\r
-\r
-            do\r
-            {\r
-                if (shouldExit())\r
-                    return ThreadPoolJob::jobHasFinished;\r
-\r
-            } while (! mmLock.retryLock());\r
-        }\r
-\r
-        if (! initialiseOnThread())\r
-        {\r
-            hasInitialised = false;\r
-\r
-            return ThreadPoolJob::jobHasFinished;\r
-        }\r
-\r
-        hasInitialised = true;\r
-\r
-        while (! shouldExit())\r
-        {\r
-           #if JUCE_IOS\r
-            if (backgroundProcessCheck.isBackgroundProcess())\r
-            {\r
-                repaintEvent.wait (300);\r
-                repaintEvent.reset();\r
-                continue;\r
-            }\r
-           #endif\r
-\r
-            if (shouldExit())\r
-                break;\r
-\r
-           #if JUCE_MAC\r
-            if (context.continuousRepaint)\r
-            {\r
-                repaintEvent.wait (-1);\r
-                renderFrame();\r
-            }\r
-            else\r
-           #endif\r
-            if (! renderFrame())\r
-                repaintEvent.wait (5); // failed to render, so avoid a tight fail-loop.\r
-            else if (! context.continuousRepaint && ! shouldExit())\r
-                repaintEvent.wait (-1);\r
-\r
-            repaintEvent.reset();\r
-        }\r
-\r
-        hasInitialised = false;\r
-        context.makeActive();\r
-        shutdownOnThread();\r
-        OpenGLContext::deactivateCurrentContext();\r
-\r
-        return ThreadPoolJob::jobHasFinished;\r
-    }\r
-\r
-    bool initialiseOnThread()\r
+    InitResult initialiseOnThread()\r
     {\r
         // On android, this can get called twice, so drop any previous state.\r
         associatedObjectNames.clear();\r
@@ -605,8 +616,8 @@ public:
 \r
         context.makeActive();\r
 \r
-        if (! nativeContext->initialiseOnRenderThread (context))\r
-            return false;\r
+        if (const auto nativeResult = nativeContext->initialiseOnRenderThread (context); nativeResult != InitResult::success)\r
+            return nativeResult;\r
 \r
        #if JUCE_ANDROID\r
         // On android the context may be created in initialiseOnRenderThread\r
@@ -622,6 +633,21 @@ public:
             bindVertexArray();\r
         }\r
 \r
+       #if JUCE_DEBUG\r
+        if (getOpenGLVersion() >= Version { 4, 3 } && glDebugMessageCallback != nullptr)\r
+        {\r
+            glEnable (GL_DEBUG_OUTPUT);\r
+            glDebugMessageCallback ([] (GLenum type, GLenum, GLuint, GLenum severity, GLsizei, const GLchar* message, const void*)\r
+            {\r
+                // This may reiterate issues that are also flagged by JUCE_CHECK_OPENGL_ERROR.\r
+                // The advantage of this callback is that it will catch *all* errors, even if we\r
+                // forget to check manually.\r
+                DBG ("OpenGL DBG message: " << message);\r
+                jassertquiet (type != GL_DEBUG_TYPE_ERROR && severity != GL_DEBUG_SEVERITY_HIGH);\r
+            }, nullptr);\r
+        }\r
+       #endif\r
+\r
         const auto currentViewportArea = areaAndScale.get().area;\r
         glViewport (0, 0, currentViewportArea.getWidth(), currentViewportArea.getHeight());\r
 \r
@@ -638,12 +664,7 @@ public:
         if (context.renderer != nullptr)\r
             context.renderer->newOpenGLContextCreated();\r
 \r
-       #if JUCE_MAC\r
-        jassert (cvDisplayLinkWrapper != nullptr);\r
-        nativeContext->setNominalVideoRefreshPeriodS (cvDisplayLinkWrapper->getNominalVideoRefreshPeriodS());\r
-       #endif\r
-\r
-        return true;\r
+        return InitResult::success;\r
     }\r
 \r
     void shutdownOnThread()\r
@@ -706,36 +727,23 @@ public:
         WaitableEvent finishedSignal;\r
     };\r
 \r
-    bool doWorkWhileWaitingForLock (bool contextIsAlreadyActive)\r
+    void doWorkWhileWaitingForLock (ScopedContextActivator& contextActivator)\r
     {\r
-        bool contextActivated = false;\r
-\r
-        for (OpenGLContext::AsyncWorker::Ptr work = workQueue.removeAndReturn (0);\r
-             work != nullptr && (! shouldExit()); work = workQueue.removeAndReturn (0))\r
+        while (const auto work = workQueue.removeAndReturn (0))\r
         {\r
-            if ((! contextActivated) && (! contextIsAlreadyActive))\r
-            {\r
-                if (! context.makeActive())\r
-                    break;\r
-\r
-                contextActivated = true;\r
-            }\r
+            if (renderThread->isListChanging() || ! contextActivator.activate (context))\r
+                break;\r
 \r
             NativeContext::Locker locker (*nativeContext);\r
 \r
             (*work) (context);\r
             clearGLError();\r
         }\r
-\r
-        if (contextActivated)\r
-            OpenGLContext::deactivateCurrentContext();\r
-\r
-        return shouldExit();\r
     }\r
 \r
-    void execute (OpenGLContext::AsyncWorker::Ptr workerToUse, bool shouldBlock, bool calledFromDestructor = false)\r
+    void execute (OpenGLContext::AsyncWorker::Ptr workerToUse, bool shouldBlock)\r
     {\r
-        if (calledFromDestructor || ! destroying)\r
+        if (! isFlagSet (state, StateFlags::pendingDestruction))\r
         {\r
             if (shouldBlock)\r
             {\r
@@ -743,7 +751,7 @@ public:
                 OpenGLContext::AsyncWorker::Ptr worker (*blocker);\r
                 workQueue.add (worker);\r
 \r
-                messageManagerLock.abort();\r
+                renderThread->abortLock();\r
                 context.triggerRepaint();\r
 \r
                 blocker->block();\r
@@ -752,7 +760,7 @@ public:
             {\r
                 workQueue.add (std::move (workerToUse));\r
 \r
-                messageManagerLock.abort();\r
+                renderThread->abortLock();\r
                 context.triggerRepaint();\r
             }\r
         }\r
@@ -768,6 +776,180 @@ public:
         return dynamic_cast<CachedImage*> (c.getCachedComponentImage());\r
     }\r
 \r
+    class RenderThread\r
+    {\r
+    public:\r
+        RenderThread() = default;\r
+\r
+        ~RenderThread()\r
+        {\r
+            flags.setDestructing();\r
+            thread.join();\r
+        }\r
+\r
+        void add (CachedImage* x)\r
+        {\r
+            const std::scoped_lock lock { listMutex };\r
+            images.push_back (x);\r
+        }\r
+\r
+        void remove (CachedImage* x)\r
+        {\r
+            JUCE_ASSERT_MESSAGE_THREAD;\r
+\r
+            flags.setSafe (false);\r
+            abortLock();\r
+\r
+            {\r
+                const std::scoped_lock lock { callbackMutex, listMutex };\r
+                images.remove (x);\r
+            }\r
+\r
+            flags.setSafe (true);\r
+        }\r
+\r
+        bool contains (CachedImage* x)\r
+        {\r
+            const std::scoped_lock lock { listMutex };\r
+            return std::find (images.cbegin(), images.cend(), x) != images.cend();\r
+        }\r
+\r
+        void triggerRepaint()   { flags.setRenderRequested(); }\r
+\r
+        void abortLock()        { messageManagerLock.abort(); }\r
+\r
+        bool isListChanging()   { return ! flags.isSafe(); }\r
+\r
+    private:\r
+        RenderStatus renderAll()\r
+        {\r
+            auto result = RenderStatus::noWork;\r
+\r
+            const std::scoped_lock lock { callbackMutex, listMutex };\r
+\r
+            for (auto* x : images)\r
+            {\r
+                listMutex.unlock();\r
+                const ScopeGuard scope { [&] { listMutex.lock(); } };\r
+\r
+                const auto status = x->renderFrame (messageManagerLock);\r
+\r
+                switch (status)\r
+                {\r
+                    case RenderStatus::noWork: break;\r
+                    case RenderStatus::nominal: result = RenderStatus::nominal; break;\r
+                    case RenderStatus::messageThreadAborted: return RenderStatus::messageThreadAborted;\r
+                }\r
+\r
+            }\r
+\r
+            return result;\r
+        }\r
+\r
+        /*  Allows the main thread to communicate changes to the render thread.\r
+\r
+            When the render thread needs to change in some way (asked to resume rendering,\r
+            a renderer is added/removed, or the thread needs to stop prior to destruction),\r
+            the main thread can set the appropriate flag on this structure. The render thread\r
+            will call waitForWork() repeatedly, pausing when the render thread has no work to do,\r
+            and resuming when requested by the main thread.\r
+        */\r
+        class Flags\r
+        {\r
+        public:\r
+            void setDestructing()       { update ([] (auto& f) { f |= destructorCalled; }); }\r
+            void setRenderRequested()   { update ([] (auto& f) { f |= renderRequested;  }); }\r
+\r
+            void setSafe (const bool safe)\r
+            {\r
+                update ([safe] (auto& f)\r
+                {\r
+                    if (safe)\r
+                        f |= listSafe;\r
+                    else\r
+                        f &= ~listSafe;\r
+                });\r
+            }\r
+\r
+            bool isSafe()\r
+            {\r
+                const std::scoped_lock lock { mutex };\r
+                return (flags & listSafe) != 0;\r
+            }\r
+\r
+            /*  Blocks until the 'safe' flag is set, and at least one other flag is set.\r
+                After returning, the renderRequested flag will be unset.\r
+                Returns true if rendering should continue.\r
+            */\r
+            bool waitForWork (bool requestRender)\r
+            {\r
+                std::unique_lock lock { mutex };\r
+                flags |= (requestRender ? renderRequested : 0);\r
+                condvar.wait (lock, [this] { return flags > listSafe; });\r
+                flags &= ~renderRequested;\r
+                return ((flags & destructorCalled) == 0);\r
+            }\r
+\r
+        private:\r
+            template <typename Fn>\r
+            void update (Fn fn)\r
+            {\r
+                {\r
+                    const std::scoped_lock lock { mutex };\r
+                    fn (flags);\r
+                }\r
+\r
+                condvar.notify_one();\r
+            }\r
+\r
+            enum\r
+            {\r
+                renderRequested  = 1 << 0,\r
+                destructorCalled = 1 << 1,\r
+                listSafe         = 1 << 2\r
+            };\r
+\r
+            std::mutex mutex;\r
+            std::condition_variable condvar;\r
+            int flags = listSafe;\r
+        };\r
+\r
+        MessageManager::Lock messageManagerLock;\r
+        std::mutex listMutex, callbackMutex;\r
+        std::list<CachedImage*> images;\r
+        Flags flags;\r
+\r
+        std::thread thread { [this]\r
+        {\r
+            Thread::setCurrentThreadName ("OpenGL Renderer");\r
+            while (flags.waitForWork (renderAll() != RenderStatus::noWork)) {}\r
+        } };\r
+    };\r
+\r
+    void refreshDisplayLinkConnection()\r
+    {\r
+       #if JUCE_MAC\r
+        if (context.continuousRepaint)\r
+        {\r
+            connection.emplace (sharedDisplayLinks->registerFactory ([this] (CGDirectDisplayID display)\r
+            {\r
+                return [this, display]\r
+                {\r
+                    if (auto* view = nativeContext->getNSView())\r
+                        if (auto* window = [view window])\r
+                            if (auto* screen = [window screen])\r
+                                if (display == ScopedDisplayLink::getDisplayIdForScreen (screen))\r
+                                    triggerRepaint();\r
+                };\r
+            }));\r
+        }\r
+        else\r
+        {\r
+            connection.reset();\r
+        }\r
+       #endif\r
+    }\r
+\r
     //==============================================================================\r
     friend class NativeContext;\r
     std::unique_ptr<NativeContext> nativeContext;\r
@@ -775,6 +957,8 @@ public:
     OpenGLContext& context;\r
     Component& component;\r
 \r
+    SharedResourcePointer<RenderThread> renderThread;\r
+\r
     OpenGLFrameBuffer cachedImageFrameBuffer;\r
     RectangleList<int> validArea;\r
     Rectangle<int> lastScreenBounds;\r
@@ -785,102 +969,101 @@ public:
     StringArray associatedObjectNames;\r
     ReferenceCountedArray<ReferenceCountedObject> associatedObjects;\r
 \r
-    WaitableEvent canPaintNowFlag, finishedPaintingFlag, repaintEvent { true };\r
+    WaitableEvent canPaintNowFlag, finishedPaintingFlag;\r
    #if JUCE_OPENGL_ES\r
     bool shadersAvailable = true;\r
    #else\r
     bool shadersAvailable = false;\r
    #endif\r
     bool textureNpotSupported = false;\r
-    std::atomic<bool> hasInitialised { false }, needsUpdate { true }, destroying { false };\r
-    uint32 lastMMLockReleaseTime = 0;\r
+    std::chrono::steady_clock::time_point lastMMLockReleaseTime{};\r
 \r
    #if JUCE_MAC\r
     NSView* getCurrentView() const\r
     {\r
+        JUCE_ASSERT_MESSAGE_THREAD;\r
+\r
         if (auto* peer = component.getPeer())\r
             return static_cast<NSView*> (peer->getNativeHandle());\r
 \r
         return nullptr;\r
     }\r
 \r
-    NSScreen* getCurrentScreen() const\r
+    NSWindow* getCurrentWindow() const\r
     {\r
         JUCE_ASSERT_MESSAGE_THREAD;\r
 \r
         if (auto* view = getCurrentView())\r
-            if (auto* window = [view window])\r
-                return [window screen];\r
+            return [view window];\r
 \r
         return nullptr;\r
     }\r
 \r
-    struct CVDisplayLinkWrapper\r
+    NSScreen* getCurrentScreen() const\r
     {\r
-        explicit CVDisplayLinkWrapper (CachedImage& cachedImageIn)\r
-            : cachedImage (cachedImageIn),\r
-              continuousRepaint (cachedImageIn.context.continuousRepaint.load())\r
-        {\r
-            CVDisplayLinkCreateWithActiveCGDisplays (&displayLink);\r
-            CVDisplayLinkSetOutputCallback (displayLink, &displayLinkCallback, this);\r
-            CVDisplayLinkStart (displayLink);\r
-        }\r
-\r
-        double getNominalVideoRefreshPeriodS() const\r
-        {\r
-            const auto nominalVideoRefreshPeriod = CVDisplayLinkGetNominalOutputVideoRefreshPeriod (displayLink);\r
+        JUCE_ASSERT_MESSAGE_THREAD;\r
 \r
-            if ((nominalVideoRefreshPeriod.flags & kCVTimeIsIndefinite) == 0)\r
-                return (double) nominalVideoRefreshPeriod.timeValue / (double) nominalVideoRefreshPeriod.timeScale;\r
+        if (auto* window = getCurrentWindow())\r
+            return [window screen];\r
 \r
-            return 0.0;\r
-        }\r
+        return nullptr;\r
+    }\r
 \r
-        /*  Returns true if updated, or false otherwise. */\r
-        bool updateActiveDisplay()\r
-        {\r
-            auto* oldScreen = std::exchange (currentScreen, cachedImage.getCurrentScreen());\r
+    void updateScreen()\r
+    {\r
+        const auto screen = getCurrentScreen();\r
+        const auto display = ScopedDisplayLink::getDisplayIdForScreen (screen);\r
 \r
-            if (oldScreen == currentScreen)\r
-                return false;\r
+        if (lastDisplay.exchange (display) == display)\r
+            return;\r
 \r
-            for (NSScreen* screen in [NSScreen screens])\r
-                if (screen == currentScreen)\r
-                    if (NSNumber* number = [[screen deviceDescription] objectForKey: @"NSScreenNumber"])\r
-                        CVDisplayLinkSetCurrentCGDisplay (displayLink, [number unsignedIntValue]);\r
+        const auto newRefreshPeriod = sharedDisplayLinks->getNominalVideoRefreshPeriodSForScreen (display);\r
 \r
-            return true;\r
-        }\r
+        if (newRefreshPeriod != 0.0 && std::exchange (refreshPeriod, newRefreshPeriod) != newRefreshPeriod)\r
+            nativeContext->setNominalVideoRefreshPeriodS (newRefreshPeriod);\r
 \r
-        ~CVDisplayLinkWrapper()\r
-        {\r
-            CVDisplayLinkStop (displayLink);\r
-            CVDisplayLinkRelease (displayLink);\r
-        }\r
+        updateColourSpace();\r
+    }\r
 \r
-        static CVReturn displayLinkCallback (CVDisplayLinkRef, const CVTimeStamp*, const CVTimeStamp*,\r
-                                             CVOptionFlags, CVOptionFlags*, void* displayLinkContext)\r
-        {\r
-            auto* self = reinterpret_cast<CVDisplayLinkWrapper*> (displayLinkContext);\r
+    void updateColourSpace()\r
+    {\r
+        if (auto* view = nativeContext->getNSView())\r
+            if (auto* window = [view window])\r
+                [window setColorSpace: [NSColorSpace sRGBColorSpace]];\r
+    }\r
 \r
-            if (self->continuousRepaint)\r
-                self->cachedImage.repaintEvent.signal();\r
+    std::atomic<CGDirectDisplayID> lastDisplay { 0 };\r
+    double refreshPeriod = 0.0;\r
 \r
-            return kCVReturnSuccess;\r
-        }\r
+    FunctionNotificationCenterObserver observer { NSWindowDidChangeScreenNotification,\r
+                                                  getCurrentWindow(),\r
+                                                  [this] { updateScreen(); } };\r
 \r
-        CachedImage& cachedImage;\r
-        const bool continuousRepaint;\r
-        CVDisplayLinkRef displayLink;\r
-        NSScreen* currentScreen = nullptr;\r
-    };\r
+    // Note: the NSViewComponentPeer also has a SharedResourcePointer<PerScreenDisplayLinks> to\r
+    // avoid unnecessarily duplicating display-link threads.\r
+    SharedResourcePointer<PerScreenDisplayLinks> sharedDisplayLinks;\r
 \r
-    std::unique_ptr<CVDisplayLinkWrapper> cvDisplayLinkWrapper;\r
+    // On macOS, rather than letting swapBuffers block as appropriate, we use a display link\r
+    // callback to mark the view as needing to repaint.\r
+    std::optional<PerScreenDisplayLinks::Connection> connection;\r
    #endif\r
 \r
-    std::unique_ptr<ThreadPool> renderThread;\r
+    enum StateFlags\r
+    {\r
+        pendingRender           = 1 << 0,\r
+        paintComponents         = 1 << 1,\r
+        pendingDestruction      = 1 << 2,\r
+        initialised             = 1 << 3,\r
+\r
+        // Flags that may change state after each frame\r
+        transient               = pendingRender | paintComponents,\r
+\r
+        // Flags that should retain their state after each frame\r
+        persistent              = initialised | pendingDestruction\r
+    };\r
+\r
+    std::atomic<int> state { 0 };\r
     ReferenceCountedArray<OpenGLContext::AsyncWorker, CriticalSection> workQueue;\r
-    MessageManager::Lock messageManagerLock;\r
 \r
    #if JUCE_IOS\r
     iOSBackgroundProcessCheck backgroundProcessCheck;\r
@@ -971,16 +1154,6 @@ public:
     }\r
    #endif\r
 \r
-    void update()\r
-    {\r
-        auto& comp = *getComponent();\r
-\r
-        if (canBeAttached (comp))\r
-            start();\r
-        else\r
-            stop();\r
-    }\r
-\r
 private:\r
     OpenGLContext& context;\r
 \r
@@ -1037,7 +1210,7 @@ private:
         if (auto* cachedImage = CachedImage::get (comp))\r
         {\r
             cachedImage->start(); // (must wait until this is attached before starting its thread)\r
-            cachedImage->updateViewportSize (true);\r
+            cachedImage->updateViewportSize();\r
 \r
             startTimer (400);\r
         }\r
@@ -1082,13 +1255,16 @@ void OpenGLContext::setContinuousRepainting (bool shouldContinuouslyRepaint) noe
 {\r
     continuousRepaint = shouldContinuouslyRepaint;\r
 \r
-    #if JUCE_MAC\r
-     if (auto* component = getTargetComponent())\r
-     {\r
-         detach();\r
-         attachment.reset (new Attachment (*this, *component));\r
-     }\r
-    #endif\r
+   #if JUCE_MAC\r
+    if (auto* component = getTargetComponent())\r
+    {\r
+        detach();\r
+        attachment.reset (new Attachment (*this, *component));\r
+    }\r
+\r
+    if (auto* cachedImage = getCachedImage())\r
+        cachedImage->refreshDisplayLinkConnection();\r
+   #endif\r
 \r
     triggerRepaint();\r
 }\r
@@ -1351,7 +1527,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
         struct OverlayShaderProgram  : public ReferenceCountedObject\r
         {\r
             OverlayShaderProgram (OpenGLContext& context)\r
-                : program (context), builder (program), params (program)\r
+                : program (context), params (program)\r
             {}\r
 \r
             static const OverlayShaderProgram& select (OpenGLContext& context)\r
@@ -1369,11 +1545,12 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
                 return *program;\r
             }\r
 \r
-            struct ProgramBuilder\r
+            struct BuiltProgram : public OpenGLShaderProgram\r
             {\r
-                ProgramBuilder (OpenGLShaderProgram& prog)\r
+                explicit BuiltProgram (OpenGLContext& ctx)\r
+                    : OpenGLShaderProgram (ctx)\r
                 {\r
-                    prog.addVertexShader (OpenGLHelpers::translateVertexShaderToV3 (\r
+                    addVertexShader (OpenGLHelpers::translateVertexShaderToV3 (\r
                         "attribute " JUCE_HIGHP " vec2 position;"\r
                         "uniform " JUCE_HIGHP " vec2 screenSize;"\r
                         "uniform " JUCE_HIGHP " float textureBounds[4];"\r
@@ -1387,7 +1564,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
                           "texturePos = vec2 (texturePos.x, vOffsetAndScale.x + vOffsetAndScale.y * texturePos.y);"\r
                         "}"));\r
 \r
-                    prog.addFragmentShader (OpenGLHelpers::translateFragmentShaderToV3 (\r
+                    addFragmentShader (OpenGLHelpers::translateFragmentShaderToV3 (\r
                         "uniform sampler2D imageTexture;"\r
                         "varying " JUCE_HIGHP " vec2 texturePos;"\r
                         "void main()"\r
@@ -1395,7 +1572,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
                           "gl_FragColor = texture2D (imageTexture, texturePos);"\r
                         "}"));\r
 \r
-                    prog.link();\r
+                    link();\r
                 }\r
             };\r
 \r
@@ -1424,8 +1601,7 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
                 OpenGLShaderProgram::Uniform screenSize, imageTexture, textureBounds, vOffsetAndScale;\r
             };\r
 \r
-            OpenGLShaderProgram program;\r
-            ProgramBuilder builder;\r
+            BuiltProgram program;\r
             Params params;\r
         };\r
 \r
@@ -1471,40 +1647,56 @@ void OpenGLContext::copyTexture (const Rectangle<int>& targetClipArea,
 }\r
 \r
 #if JUCE_ANDROID\r
-EGLDisplay OpenGLContext::NativeContext::display = EGL_NO_DISPLAY;\r
-EGLDisplay OpenGLContext::NativeContext::config;\r
 \r
-void OpenGLContext::NativeContext::surfaceCreated (LocalRef<jobject> holder)\r
+void OpenGLContext::NativeContext::surfaceCreated (LocalRef<jobject>)\r
 {\r
-    ignoreUnused (holder);\r
-\r
-    if (auto* cachedImage = CachedImage::get (component))\r
     {\r
-        if (auto* pool = cachedImage->renderThread.get())\r
+        const std::lock_guard lock { nativeHandleMutex };\r
+\r
+        jassert (hasInitialised);\r
+\r
+        // has the context already attached?\r
+        jassert (surface.get() == EGL_NO_SURFACE && context.get() == EGL_NO_CONTEXT);\r
+\r
+        const auto window = getNativeWindow();\r
+\r
+        if (window == nullptr)\r
         {\r
-            if (! pool->contains (cachedImage))\r
-            {\r
-                cachedImage->resume();\r
-                cachedImage->context.triggerRepaint();\r
-            }\r
+            // failed to get a pointer to the native window so bail out\r
+            jassertfalse;\r
+            return;\r
         }\r
+\r
+        // create the surface\r
+        surface.reset (eglCreateWindowSurface (display, config, window.get(), nullptr));\r
+        jassert (surface.get() != EGL_NO_SURFACE);\r
+\r
+        // create the OpenGL context\r
+        EGLint contextAttribs[] = { EGL_CONTEXT_CLIENT_VERSION, 2, EGL_NONE };\r
+        context.reset (eglCreateContext (display, config, EGL_NO_CONTEXT, contextAttribs));\r
+        jassert (context.get() != EGL_NO_CONTEXT);\r
+    }\r
+\r
+    if (auto* cached = CachedImage::get (component))\r
+    {\r
+        cached->resume();\r
+        cached->triggerRepaint();\r
     }\r
 }\r
 \r
-void OpenGLContext::NativeContext::surfaceDestroyed (LocalRef<jobject> holder)\r
+void OpenGLContext::NativeContext::surfaceDestroyed (LocalRef<jobject>)\r
 {\r
-    ignoreUnused (holder);\r
+    if (auto* cached = CachedImage::get (component))\r
+        cached->pause();\r
 \r
-    // unlike the name suggests this will be called just before the\r
-    // surface is destroyed. We need to pause the render thread.\r
-    if (auto* cachedImage = CachedImage::get (component))\r
     {\r
-        cachedImage->pause();\r
+        const std::lock_guard lock { nativeHandleMutex };\r
 \r
-        if (auto* threadPool = cachedImage->renderThread.get())\r
-            threadPool->waitForJobToFinish (cachedImage, -1);\r
+        context.reset (EGL_NO_CONTEXT);\r
+        surface.reset (EGL_NO_SURFACE);\r
     }\r
 }\r
+\r
 #endif\r
 \r
 } // namespace juce\r
index b272ee2a3af097d172fa0e1b91b962d271c15445..86191f842e7b073160649553ff51c13b54f59ff4 100644 (file)
@@ -136,8 +136,10 @@ public:
     /** OpenGL versions, used by setOpenGLVersionRequired(). */\r
     enum OpenGLVersion\r
     {\r
-        defaultGLVersion = 0,\r
-        openGL3_2\r
+        defaultGLVersion = 0, ///< Whatever the device decides to give us, normally a compatibility profile\r
+        openGL3_2,            ///< 3.2 Core profile\r
+        openGL4_1,            ///< 4.1 Core profile, the latest supported by macOS at time of writing\r
+        openGL4_3             ///< 4.3 Core profile, will enable improved debugging support when building in Debug\r
     };\r
 \r
     /** Sets a preference for the version of GL that this context should use, if possible.\r
@@ -318,6 +320,13 @@ public:
    #endif\r
 \r
 private:\r
+    enum class InitResult\r
+    {\r
+        fatal,\r
+        retry,\r
+        success\r
+    };\r
+\r
     friend class OpenGLTexture;\r
 \r
     class CachedImage;\r
index 56380e51373de7e59a0befe584578c93e42657f7..1ec0f17fc7dc415d4054eaeaed59eee0a4c6f441 100644 (file)
@@ -964,8 +964,10 @@ struct StateHelpers
     //==============================================================================\r
     struct ActiveTextures\r
     {\r
-        ActiveTextures (const OpenGLContext& c) noexcept  : context (c)\r
-        {}\r
+        explicit ActiveTextures (const OpenGLContext& c) noexcept\r
+            : context (c)\r
+        {\r
+        }\r
 \r
         void clear() noexcept\r
         {\r
@@ -979,23 +981,28 @@ struct StateHelpers
             {\r
                 quadQueue.flush();\r
 \r
-                for (int i = 3; --i >= 0;)\r
+                for (int i = numTextures; --i >= 0;)\r
                 {\r
                     if ((texturesEnabled & (1 << i)) != (textureIndexMask & (1 << i)))\r
                     {\r
                         setActiveTexture (i);\r
                         JUCE_CHECK_OPENGL_ERROR\r
 \r
+                        const auto thisTextureEnabled = (textureIndexMask & (1 << i)) != 0;\r
+\r
+                        if (! thisTextureEnabled)\r
+                            currentTextureID[i] = 0;\r
+\r
                        #if ! JUCE_ANDROID\r
-                        if ((textureIndexMask & (1 << i)) != 0)\r
-                            glEnable (GL_TEXTURE_2D);\r
-                        else\r
+                        if (needsToEnableTexture)\r
                         {\r
-                            glDisable (GL_TEXTURE_2D);\r
-                            currentTextureID[i] = 0;\r
-                        }\r
+                            if (thisTextureEnabled)\r
+                                glEnable (GL_TEXTURE_2D);\r
+                            else\r
+                                glDisable (GL_TEXTURE_2D);\r
 \r
-                        clearGLError();\r
+                            JUCE_CHECK_OPENGL_ERROR\r
+                        }\r
                        #endif\r
                     }\r
                 }\r
@@ -1079,6 +1086,7 @@ struct StateHelpers
         GLuint currentTextureID[numTextures];\r
         int texturesEnabled = 0, currentActiveTexture = -1;\r
         const OpenGLContext& context;\r
+        const bool needsToEnableTexture = contextRequiresTexture2DEnableDisable();\r
 \r
         ActiveTextures& operator= (const ActiveTextures&);\r
     };\r
index a1e8444ad082dac4466c7a361eed429101876b80..99e838fad1642768022e8e9efa58bb7ea71ebdfc 100644 (file)
 \r
   ID:                 juce_osc\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE OSC classes\r
   description:        Open Sound Control implementation.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_events\r
 \r
index 9ced7d1a237e4b4fa1222b6dd2c8bf306be231e2..7030a49f18ca124a10a20b73062dd509388efb13 100644 (file)
@@ -60,8 +60,8 @@ void InAppPurchases::getProductsInformation (const StringArray& productIdentifie
 }\r
 \r
 void InAppPurchases::purchaseProduct (const String& productIdentifier,\r
-                                      const String& upgradeProductIdentifier,\r
-                                      bool creditForUnusedSubscription)\r
+                                      [[maybe_unused]] const String& upgradeProductIdentifier,\r
+                                      [[maybe_unused]] bool creditForUnusedSubscription)\r
 {\r
    #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC\r
     pimpl->purchaseProduct (productIdentifier, upgradeProductIdentifier, creditForUnusedSubscription);\r
@@ -69,66 +69,55 @@ void InAppPurchases::purchaseProduct (const String& productIdentifier,
     Listener::PurchaseInfo purchaseInfo { Purchase { "", productIdentifier, {}, {}, {} }, {} };\r
 \r
     listeners.call ([&] (Listener& l) { l.productPurchaseFinished (purchaseInfo, false, "In-app purchases unavailable"); });\r
-    ignoreUnused (upgradeProductIdentifier, creditForUnusedSubscription);\r
    #endif\r
 }\r
 \r
-void InAppPurchases::restoreProductsBoughtList (bool includeDownloadInfo, const String& subscriptionsSharedSecret)\r
+void InAppPurchases::restoreProductsBoughtList ([[maybe_unused]] bool includeDownloadInfo, [[maybe_unused]] const String& subscriptionsSharedSecret)\r
 {\r
    #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC\r
     pimpl->restoreProductsBoughtList (includeDownloadInfo, subscriptionsSharedSecret);\r
    #else\r
     listeners.call ([] (Listener& l) { l.purchasesListRestored ({}, false, "In-app purchases unavailable"); });\r
-    ignoreUnused (includeDownloadInfo, subscriptionsSharedSecret);\r
    #endif\r
 }\r
 \r
-void InAppPurchases::consumePurchase (const String& productIdentifier, const String& purchaseToken)\r
+void InAppPurchases::consumePurchase (const String& productIdentifier, [[maybe_unused]] const String& purchaseToken)\r
 {\r
    #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC\r
     pimpl->consumePurchase (productIdentifier, purchaseToken);\r
    #else\r
     listeners.call ([&] (Listener& l) { l.productConsumed (productIdentifier, false, "In-app purchases unavailable"); });\r
-    ignoreUnused (purchaseToken);\r
    #endif\r
 }\r
 \r
 void InAppPurchases::addListener (Listener* l)      { listeners.add (l); }\r
 void InAppPurchases::removeListener (Listener* l)   { listeners.remove (l); }\r
 \r
-void InAppPurchases::startDownloads  (const Array<Download*>& downloads)\r
+void InAppPurchases::startDownloads  ([[maybe_unused]] const Array<Download*>& downloads)\r
 {\r
    #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC\r
     pimpl->startDownloads (downloads);\r
-   #else\r
-    ignoreUnused (downloads);\r
    #endif\r
 }\r
 \r
-void InAppPurchases::pauseDownloads  (const Array<Download*>& downloads)\r
+void InAppPurchases::pauseDownloads  ([[maybe_unused]] const Array<Download*>& downloads)\r
 {\r
    #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC\r
     pimpl->pauseDownloads (downloads);\r
-   #else\r
-    ignoreUnused (downloads);\r
    #endif\r
 }\r
 \r
-void InAppPurchases::resumeDownloads (const Array<Download*>& downloads)\r
+void InAppPurchases::resumeDownloads ([[maybe_unused]] const Array<Download*>& downloads)\r
 {\r
    #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC\r
     pimpl->resumeDownloads (downloads);\r
-   #else\r
-    ignoreUnused (downloads);\r
    #endif\r
 }\r
 \r
-void InAppPurchases::cancelDownloads (const Array<Download*>& downloads)\r
+void InAppPurchases::cancelDownloads ([[maybe_unused]] const Array<Download*>& downloads)\r
 {\r
    #if JUCE_ANDROID || JUCE_IOS || JUCE_MAC\r
     pimpl->cancelDownloads (downloads);\r
-   #else\r
-    ignoreUnused (downloads);\r
    #endif\r
 }\r
 \r
index 2f89af71d39960025041ce175bee776d84348b2e..d67755b83d02c0faf767fe1d16fc3347a4e20102 100644 (file)
@@ -261,12 +261,10 @@ public:
                   "and only a single subscription can be upgraded/downgraded. Use the updated purchaseProduct method "\r
                   "which takes a single String argument.")]]\r
     void purchaseProduct (const String& productIdentifier,\r
-                          bool isSubscription,\r
+                          [[maybe_unused]] bool isSubscription,\r
                           const StringArray& upgradeOrDowngradeFromSubscriptionsWithProductIdentifiers = {},\r
                           bool creditForUnusedSubscription = true)\r
     {\r
-\r
-        ignoreUnused (isSubscription);\r
         purchaseProduct (productIdentifier,\r
                          upgradeOrDowngradeFromSubscriptionsWithProductIdentifiers[0],\r
                          creditForUnusedSubscription);\r
index d5726bf1dd3d36ec3911a493bbb7f2eaccc7a94e..db9b0ab470da767913bd37038772bd9f14006b0a 100644 (file)
 \r
   ID:                 juce_product_unlocking\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE Online marketplace support\r
   description:        Classes for online product authentication\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_cryptography\r
 \r
index 9872a0805750f4e716e2fdce9387f5a7882133be..90dda0546bd817510a3c65f02e99acfe261b2345 100644 (file)
@@ -58,7 +58,7 @@ struct OnlineUnlockForm::OverlayComp  : public Component,
             cancelButton->addListener (this);\r
         }\r
 \r
-        startThread (4);\r
+        startThread (Priority::normal);\r
     }\r
 \r
     ~OverlayComp() override\r
index f2d527ee4ff06fd530f92c56f8bc8e7c64b4990e..0114483b9b2b06d4c26b434f53117010e75215d1 100644 (file)
@@ -314,6 +314,14 @@ void OnlineUnlockStatus::MachineIDUtilities::addMACAddressesToList (StringArray&
         ids.add (getEncodedIDString (address.toString()));\r
 }\r
 \r
+String OnlineUnlockStatus::MachineIDUtilities::getUniqueMachineID()\r
+{\r
+    return getEncodedIDString (SystemStats::getUniqueDeviceID());\r
+}\r
+\r
+JUCE_BEGIN_IGNORE_WARNINGS_GCC_LIKE ("-Wdeprecated-declarations")\r
+JUCE_BEGIN_IGNORE_WARNINGS_MSVC (4996)\r
+\r
 StringArray OnlineUnlockStatus::MachineIDUtilities::getLocalMachineIDs()\r
 {\r
     auto identifiers = SystemStats::getDeviceIdentifiers();\r
@@ -329,6 +337,9 @@ StringArray OnlineUnlockStatus::getLocalMachineIDs()
     return MachineIDUtilities::getLocalMachineIDs();\r
 }\r
 \r
+JUCE_END_IGNORE_WARNINGS_GCC_LIKE\r
+JUCE_END_IGNORE_WARNINGS_MSVC\r
+\r
 void OnlineUnlockStatus::userCancelled()\r
 {\r
 }\r
@@ -378,22 +389,19 @@ bool OnlineUnlockStatus::applyKeyFile (String keyFileContent)
     return false;\r
 }\r
 \r
-static bool canConnectToWebsite (const URL& url)\r
-{\r
-    return url.createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)\r
-                                        .withConnectionTimeoutMs (2000)) != nullptr;\r
-}\r
-\r
 static bool areMajorWebsitesAvailable()\r
 {\r
-    const char* urlsToTry[] = { "http://google.com",  "http://bing.com",  "http://amazon.com",\r
-                                "https://google.com", "https://bing.com", "https://amazon.com", nullptr};\r
-\r
-    for (const char** url = urlsToTry; *url != nullptr; ++url)\r
-        if (canConnectToWebsite (URL (*url)))\r
-            return true;\r
+    static constexpr const char* const urlsToTry[] = { "http://google.com",  "http://bing.com",  "http://amazon.com",\r
+                                                       "https://google.com", "https://bing.com", "https://amazon.com" };\r
+    const auto canConnectToWebsite = [] (auto url)\r
+    {\r
+        return URL (url).createInputStream (URL::InputStreamOptions (URL::ParameterHandling::inAddress)\r
+                                                .withConnectionTimeoutMs (2000)) != nullptr;\r
+    };\r
 \r
-    return false;\r
+    return std::any_of (std::begin (urlsToTry),\r
+                        std::end   (urlsToTry),\r
+                        canConnectToWebsite);\r
 }\r
 \r
 OnlineUnlockStatus::UnlockResult OnlineUnlockStatus::handleXmlReply (XmlElement xml)\r
index 819830d24eb5d64cf686f59345a96915574582c5..cdf9a2cfb38fba0a9e92215d2883ddda30325000 100644 (file)
@@ -242,6 +242,7 @@ public:
         /** Utility function that you may want to use in your machine-ID generation code.\r
             This adds some ID strings to the given array which represent each MAC address of the machine.\r
         */\r
+        [[deprecated ("MAC addresses are no longer reliable methods of ID generation. You should use getUniqueMachineID() instead, You can still get a list of this device's MAC addresses with MACAddress::findAllAddresses().")]]\r
         static void addMACAddressesToList (StringArray& result);\r
 \r
         /** This method calculates some machine IDs based on things like network\r
@@ -259,7 +260,14 @@ public:
             registration on machines which have had hardware added/removed\r
             since the product was first registered.\r
         */\r
+        [[deprecated ("The identifiers generated by this function are no longer reliable. Use getUniqueMachineID() instead.")]]\r
         static StringArray getLocalMachineIDs();\r
+\r
+        /** Returns an encoded unique machine ID.\r
+\r
+            @see SystemStats::getUniqueDeviceID\r
+        */\r
+        static String getUniqueMachineID();\r
     };\r
 \r
 private:\r
index b382e5a1b41304e2948de22d7c94afbfdcc4f053..bed2c811239ae95e8eb9f18dafbaa8a00c7aa6a8 100644 (file)
@@ -143,7 +143,7 @@ inline StringArray javaListOfStringToJuceStringArray (const LocalRef<jobject>& j
 }\r
 \r
 //==============================================================================\r
-constexpr unsigned char juceBillingClientCompiled[]\r
+constexpr uint8 juceBillingClientCompiled[]\r
 {\r
     0x1f, 0x8b, 0x08, 0x08, 0xa4, 0x53, 0xd0, 0x62, 0x04, 0x03, 0x63, 0x6c,\r
     0x61, 0x73, 0x73, 0x65, 0x73, 0x2e, 0x64, 0x65, 0x78, 0x00, 0x9d, 0x5a,\r
@@ -685,31 +685,27 @@ struct InAppPurchases::Pimpl
     }\r
 \r
     //==============================================================================\r
-    void startDownloads (const Array<Download*>& downloads)\r
+    void startDownloads ([[maybe_unused]] const Array<Download*>& downloads)\r
     {\r
         // Not available on this platform.\r
-        ignoreUnused (downloads);\r
         jassertfalse;\r
     }\r
 \r
-    void pauseDownloads (const Array<Download*>& downloads)\r
+    void pauseDownloads ([[maybe_unused]] const Array<Download*>& downloads)\r
     {\r
         // Not available on this platform.\r
-        ignoreUnused (downloads);\r
         jassertfalse;\r
     }\r
 \r
-    void resumeDownloads (const Array<Download*>& downloads)\r
+    void resumeDownloads ([[maybe_unused]] const Array<Download*>& downloads)\r
     {\r
         // Not available on this platform.\r
-        ignoreUnused (downloads);\r
         jassertfalse;\r
     }\r
 \r
-    void cancelDownloads (const Array<Download*>& downloads)\r
+    void cancelDownloads ([[maybe_unused]] const Array<Download*>& downloads)\r
     {\r
         // Not available on this platform.\r
-        ignoreUnused (downloads);\r
         jassertfalse;\r
     }\r
 \r
@@ -724,42 +720,17 @@ private:
       METHOD (queryPurchases,                "queryPurchases",              "()V")                                                                        \\r
       METHOD (consumePurchase,               "consumePurchase",             "(Ljava/lang/String;Ljava/lang/String;)V")                                    \\r
                                                                                                                                                           \\r
-      CALLBACK (productDetailsQueryCallback, "productDetailsQueryCallback", "(JLjava/util/List;)V")                                                       \\r
-      CALLBACK (purchasesListQueryCallback,  "purchasesListQueryCallback",  "(JLjava/util/List;)V")                                                       \\r
-      CALLBACK (purchaseCompletedCallback,   "purchaseCompletedCallback",   "(JLcom/android/billingclient/api/Purchase;I)V")                              \\r
-      CALLBACK (purchaseConsumedCallback,    "purchaseConsumedCallback",    "(JLjava/lang/String;I)V")\r
+      CALLBACK (generatedCallback<&Pimpl::updateProductDetails>, "productDetailsQueryCallback", "(JLjava/util/List;)V")                                                       \\r
+      CALLBACK (generatedCallback<&Pimpl::updatePurchasesList>,  "purchasesListQueryCallback",  "(JLjava/util/List;)V")                                                       \\r
+      CALLBACK (generatedCallback<&Pimpl::purchaseCompleted>,    "purchaseCompletedCallback",   "(JLcom/android/billingclient/api/Purchase;I)V")                              \\r
+      CALLBACK (generatedCallback<&Pimpl::purchaseConsumed>,     "purchaseConsumedCallback",    "(JLjava/lang/String;I)V")\r
 \r
     DECLARE_JNI_CLASS_WITH_BYTECODE (JuceBillingClient,\r
                                      "com/rmsl/juce/JuceBillingClient",\r
                                      16,\r
-                                     juceBillingClientCompiled,\r
-                                     numElementsInArray (juceBillingClientCompiled))\r
+                                     juceBillingClientCompiled)\r
     #undef JNI_CLASS_MEMBERS\r
 \r
-    static void JNICALL productDetailsQueryCallback (JNIEnv*, jobject, jlong host, jobject productDetailsList)\r
-    {\r
-        if (auto* myself = reinterpret_cast<Pimpl*> (host))\r
-            myself->updateProductDetails (productDetailsList);\r
-    }\r
-\r
-    static void JNICALL purchasesListQueryCallback (JNIEnv*, jobject, jlong host, jobject purchasesList)\r
-    {\r
-        if (auto* myself = reinterpret_cast<Pimpl*> (host))\r
-            myself->updatePurchasesList (purchasesList);\r
-    }\r
-\r
-    static void JNICALL purchaseCompletedCallback (JNIEnv*, jobject, jlong host, jobject purchase, int responseCode)\r
-    {\r
-        if (auto* myself = reinterpret_cast<Pimpl*> (host))\r
-            myself->purchaseCompleted (purchase, responseCode);\r
-    }\r
-\r
-    static void JNICALL purchaseConsumedCallback (JNIEnv*, jobject, jlong host, jstring productIdentifier, int responseCode)\r
-    {\r
-        if (auto* myself = reinterpret_cast<Pimpl*> (host))\r
-            myself->purchaseConsumed (productIdentifier, responseCode);\r
-    }\r
-\r
     //==============================================================================\r
     bool isReady() const\r
     {\r
@@ -1041,32 +1012,32 @@ private:
         return responseCode == 0;\r
     }\r
 \r
-    void purchaseCompleted (jobject purchase, int responseCode)\r
+    static void purchaseCompleted (JNIEnv*, Pimpl& t, jobject purchase, int responseCode)\r
     {\r
-        notifyListenersAboutPurchase (buildPurchase (LocalRef<jobject> { purchase }),\r
-                                      wasSuccessful (responseCode),\r
-                                      getStatusDescriptionFromResponseCode (responseCode));\r
+        t.notifyListenersAboutPurchase (buildPurchase (LocalRef<jobject> { purchase }),\r
+                                        wasSuccessful (responseCode),\r
+                                        getStatusDescriptionFromResponseCode (responseCode));\r
     }\r
 \r
-    void purchaseConsumed (jstring productIdentifier, int responseCode)\r
+    static void purchaseConsumed (JNIEnv*, Pimpl& t, jstring productIdentifier, int responseCode)\r
     {\r
-        notifyListenersAboutConsume (juceString (LocalRef<jstring> { productIdentifier }),\r
-                                     wasSuccessful (responseCode),\r
-                                     getStatusDescriptionFromResponseCode (responseCode));\r
+        t.notifyListenersAboutConsume (juceString (LocalRef<jstring> { productIdentifier }),\r
+                                       wasSuccessful (responseCode),\r
+                                       getStatusDescriptionFromResponseCode (responseCode));\r
     }\r
 \r
-    void updateProductDetails (jobject productDetailsList)\r
+    static void updateProductDetails (JNIEnv*, Pimpl& t, jobject productDetailsList)\r
     {\r
-        jassert (! productDetailsQueryCallbackQueue.empty());\r
-        productDetailsQueryCallbackQueue.front() (LocalRef<jobject> { productDetailsList });\r
-        productDetailsQueryCallbackQueue.pop();\r
+        jassert (! t.productDetailsQueryCallbackQueue.empty());\r
+        t.productDetailsQueryCallbackQueue.front() (LocalRef<jobject> { productDetailsList });\r
+        t.productDetailsQueryCallbackQueue.pop();\r
     }\r
 \r
-    void updatePurchasesList (jobject purchasesList)\r
+    static void updatePurchasesList (JNIEnv*, Pimpl& t, jobject purchasesList)\r
     {\r
-        jassert (! purchasesListQueryCallbackQueue.empty());\r
-        purchasesListQueryCallbackQueue.front() (LocalRef<jobject> { purchasesList });\r
-        purchasesListQueryCallbackQueue.pop();\r
+        jassert (! t.purchasesListQueryCallbackQueue.empty());\r
+        t.purchasesListQueryCallbackQueue.front() (LocalRef<jobject> { purchasesList });\r
+        t.purchasesListQueryCallbackQueue.pop();\r
     }\r
 \r
     //==============================================================================\r
@@ -1099,7 +1070,4 @@ void juce_handleOnResume()
     });\r
 }\r
 \r
-\r
-InAppPurchases::Pimpl::JuceBillingClient_Class InAppPurchases::Pimpl::JuceBillingClient;\r
-\r
 } // namespace juce\r
index da0f3a6d33dbfa953c4e54e943ea3daa3f775a5b..5a317a725842f6df4aa3b1036560770a125f5dbc 100644 (file)
@@ -191,10 +191,10 @@ StringArray CameraDevice::getAvailableDevices()
     }\r
 }\r
 \r
-CameraDevice* CameraDevice::openDevice (int index,\r
-                                        int minWidth, int minHeight,\r
-                                        int maxWidth, int maxHeight,\r
-                                        bool useHighQuality)\r
+CameraDevice* CameraDevice::openDevice ([[maybe_unused]] int index,\r
+                                        [[maybe_unused]] int minWidth, [[maybe_unused]] int minHeight,\r
+                                        [[maybe_unused]] int maxWidth, [[maybe_unused]] int maxHeight,\r
+                                        [[maybe_unused]] bool useHighQuality)\r
 {\r
     jassert (juce::MessageManager::getInstance()->currentThreadHasLockedMessageManager());\r
 \r
@@ -204,9 +204,6 @@ CameraDevice* CameraDevice::openDevice (int index,
     if (d != nullptr && d->pimpl->openedOk())\r
         return d.release();\r
    #else\r
-    ignoreUnused (index, minWidth, minHeight);\r
-    ignoreUnused (maxWidth, maxHeight, useHighQuality);\r
-\r
     // Use openDeviceAsync to open a camera device on iOS or Android.\r
     jassertfalse;\r
    #endif\r
index d08cc542f9b784770050201788f0e734d79a0ae1..f6056caa9ef611534896b65d928f7df21dbe0519 100644 (file)
 \r
   ID:                 juce_video\r
   vendor:             juce\r
-  version:            7.0.2\r
+  version:            7.0.5\r
   name:               JUCE video playback and capture classes\r
   description:        Classes for playing video and capturing camera input.\r
   website:            http://www.juce.com/juce\r
   license:            GPL/Commercial\r
-  minimumCppStandard: 14\r
+  minimumCppStandard: 17\r
 \r
   dependencies:       juce_gui_extra\r
   OSXFrameworks:      AVKit AVFoundation CoreMedia\r
index 45a731cc6d5efe01c42a3ef73bf4b068247654d6..fd29bfb7bd9a64fbe297da02be516c6bbb47237e 100644 (file)
@@ -400,7 +400,7 @@ class MediaRecorderOnInfoListener     : public AndroidInterfaceImplementer
 public:\r
     struct Owner\r
     {\r
-        virtual ~Owner() {}\r
+        virtual ~Owner() = default;\r
 \r
         virtual void onInfo (LocalRef<jobject>& mediaRecorder, int what, int extra) = 0;\r
     };\r
@@ -715,7 +715,7 @@ private:
         {\r
             auto key = LocalRef<jobject> (env->CallObjectMethod (keysList, JavaList.get, i));\r
             auto jKeyName = LocalRef<jstring> ((jstring) env->CallObjectMethod (key, CameraCharacteristicsKey.getName));\r
-            auto keyName = juceString (jKeyName);\r
+            [[maybe_unused]] auto keyName = juceString (jKeyName);\r
 \r
             auto keyValue = LocalRef<jobject> (env->CallObjectMethod (characteristics, CameraCharacteristics.get, key.get()));\r
             auto jKeyValueString = LocalRef<jstring> ((jstring) env->CallObjectMethod (keyValue, JavaObject.toString));\r
@@ -747,16 +747,12 @@ private:
                     JUCE_CAMERA_LOG ("Key: " + keyName + ", value: " + keyValueString);\r
                 }\r
             }\r
-\r
-            ignoreUnused (keyName);\r
         }\r
     }\r
 \r
-    static void printPrimitiveArrayElements (const LocalRef<jobject>& keyValue, const String& keyName,\r
+    static void printPrimitiveArrayElements (const LocalRef<jobject>& keyValue, [[maybe_unused]] const String& keyName,\r
                                              const String& keyValueString)\r
     {\r
-        ignoreUnused (keyName);\r
-\r
         String result = "[";\r
 \r
         auto* env = getEnv();\r
@@ -790,7 +786,7 @@ private:
         JUCE_CAMERA_LOG ("Key: " + keyName + ", value: " + result);\r
     }\r
 \r
-    static void printRangeArrayElements (const LocalRef<jobject>& rangeArray, const String& keyName)\r
+    static void printRangeArrayElements (const LocalRef<jobject>& rangeArray, [[maybe_unused]] const String& keyName)\r
     {\r
         auto* env = getEnv();\r
 \r
@@ -809,7 +805,6 @@ private:
             result << juceString (jRangeString) << " ";\r
         }\r
 \r
-        ignoreUnused (keyName);\r
         JUCE_CAMERA_LOG ("Key: " + keyName + ", value: " + result);\r
     }\r
 \r
@@ -921,10 +916,8 @@ private:
                                                                         javaString (name).get()));\r
         }\r
 \r
-        static void printSizesLog (const Array<Rectangle<int>>& sizes, const String& className)\r
+        static void printSizesLog ([[maybe_unused]] const Array<Rectangle<int>>& sizes, [[maybe_unused]] const String& className)\r
         {\r
-            ignoreUnused (sizes, className);\r
-\r
             JUCE_CAMERA_LOG ("Sizes for class " + className);\r
 \r
           #if JUCE_CAMERA_LOG_ENABLED\r
@@ -1489,18 +1482,14 @@ private:
             Desktop::getInstance().setOrientationsEnabled (orientationsEnabled);\r
         }\r
 \r
-        void onInfo (LocalRef<jobject>& recorder, int what, int extra) override\r
+        void onInfo ([[maybe_unused]] LocalRef<jobject>& recorder, [[maybe_unused]] int what, [[maybe_unused]] int extra) override\r
         {\r
-            ignoreUnused (recorder, what, extra);\r
-\r
             JUCE_CAMERA_LOG ("MediaRecorder::OnInfo: " + getInfoStringFromCode (what)\r
                                      + ", extra code = " + String (extra));\r
         }\r
 \r
-        void onError (LocalRef<jobject>& recorder, int what, int extra) override\r
+        void onError ([[maybe_unused]] LocalRef<jobject>& recorder, [[maybe_unused]] int what, [[maybe_unused]] int extra) override\r
         {\r
-            ignoreUnused (recorder, what, extra);\r
-\r
             JUCE_CAMERA_LOG ("MediaRecorder::onError: " + getErrorStringFromCode (what)\r
                                      + ", extra code = " + String (extra));\r
         }\r
@@ -1722,26 +1711,25 @@ private:
                 //==============================================================================\r
                 #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
                    METHOD (constructor, "<init>", "(JZ)V")              \\r
-                   CALLBACK (cameraCaptureSessionCaptureCompletedCallback,         "cameraCaptureSessionCaptureCompleted",         "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/TotalCaptureResult;)V") \\r
-                   CALLBACK (cameraCaptureSessionCaptureFailedCallback,            "cameraCaptureSessionCaptureFailed",            "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/CaptureFailure;)V") \\r
-                   CALLBACK (cameraCaptureSessionCaptureProgressedCallback,        "cameraCaptureSessionCaptureProgressed",        "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/CaptureResult;)V") \\r
-                   CALLBACK (cameraCaptureSessionCaptureStartedCallback,           "cameraCaptureSessionCaptureStarted",           "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;JJ)V") \\r
-                   CALLBACK (cameraCaptureSessionCaptureSequenceAbortedCallback,   "cameraCaptureSessionCaptureSequenceAborted",   "(JZLandroid/hardware/camera2/CameraCaptureSession;I)V") \\r
-                   CALLBACK (cameraCaptureSessionCaptureSequenceCompletedCallback, "cameraCaptureSessionCaptureSequenceCompleted", "(JZLandroid/hardware/camera2/CameraCaptureSession;IJ)V")\r
-\r
-                DECLARE_JNI_CLASS_WITH_BYTECODE (CameraCaptureSessionCaptureCallback, "com/rmsl/juce/CameraCaptureSessionCaptureCallback", 21, CameraSupportByteCode, sizeof(CameraSupportByteCode))\r
+                   CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureCompletedCallback>,         "cameraCaptureSessionCaptureCompleted",         "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/TotalCaptureResult;)V") \\r
+                   CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureFailedCallback>,            "cameraCaptureSessionCaptureFailed",            "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/CaptureFailure;)V") \\r
+                   CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureProgressedCallback>,        "cameraCaptureSessionCaptureProgressed",        "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;Landroid/hardware/camera2/CaptureResult;)V") \\r
+                   CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureStartedCallback>,           "cameraCaptureSessionCaptureStarted",           "(JZLandroid/hardware/camera2/CameraCaptureSession;Landroid/hardware/camera2/CaptureRequest;JJ)V") \\r
+                   CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureSequenceAbortedCallback>,   "cameraCaptureSessionCaptureSequenceAborted",   "(JZLandroid/hardware/camera2/CameraCaptureSession;I)V") \\r
+                   CALLBACK (generatedCallback<&StillPictureTaker::cameraCaptureSessionCaptureSequenceCompletedCallback>, "cameraCaptureSessionCaptureSequenceCompleted", "(JZLandroid/hardware/camera2/CameraCaptureSession;IJ)V")\r
+\r
+                DECLARE_JNI_CLASS_WITH_BYTECODE (CameraCaptureSessionCaptureCallback, "com/rmsl/juce/CameraCaptureSessionCaptureCallback", 21, CameraSupportByteCode)\r
                 #undef JNI_CLASS_MEMBERS\r
 \r
                 LocalRef<jobject> createCaptureSessionCallback (bool createPreviewSession)\r
                 {\r
-                    return LocalRef<jobject>(getEnv()->NewObject (CameraCaptureSessionCaptureCallback,\r
-                                                                  CameraCaptureSessionCaptureCallback.constructor,\r
-                                                                  reinterpret_cast<jlong> (this),\r
-                                                                  createPreviewSession ? 1 : 0));\r
+                    return LocalRef<jobject> (getEnv()->NewObject (CameraCaptureSessionCaptureCallback,\r
+                                                                   CameraCaptureSessionCaptureCallback.constructor,\r
+                                                                   reinterpret_cast<jlong> (this),\r
+                                                                   createPreviewSession ? 1 : 0));\r
                 }\r
 \r
                 //==============================================================================\r
-\r
                 enum class State\r
                 {\r
                     idle = 0,\r
@@ -1976,122 +1964,110 @@ private:
                 }\r
 \r
                 //==============================================================================\r
-                void cameraCaptureSessionCaptureCompleted (bool isPreview, jobject session, jobject request, jobject result)\r
+                void cameraCaptureSessionCaptureCompleted (bool isPreview,\r
+                                                           [[maybe_unused]] jobject session,\r
+                                                           [[maybe_unused]] jobject request,\r
+                                                           jobject result)\r
                 {\r
                     JUCE_CAMERA_LOG ("cameraCaptureSessionCaptureCompleted()");\r
 \r
-                    ignoreUnused (session, request);\r
-\r
                     if (isPreview)\r
                         updateState (result);\r
                     else if (currentState != State::idle)\r
                         unlockFocus();\r
                 }\r
 \r
-                void cameraCaptureSessionCaptureFailed (bool isPreview, jobject session, jobject request, jobject failure)\r
+                void cameraCaptureSessionCaptureFailed ([[maybe_unused]] bool isPreview,\r
+                                                        [[maybe_unused]] jobject session,\r
+                                                        [[maybe_unused]] jobject request,\r
+                                                        [[maybe_unused]] jobject failure)\r
                 {\r
                     JUCE_CAMERA_LOG ("cameraCaptureSessionCaptureFailed()");\r
-\r
-                    ignoreUnused (isPreview, session, request, failure);\r
                 }\r
 \r
-                void cameraCaptureSessionCaptureProgressed (bool isPreview, jobject session, jobject request, jobject partialResult)\r
+                void cameraCaptureSessionCaptureProgressed (bool isPreview,\r
+                                                            [[maybe_unused]] jobject session,\r
+                                                            [[maybe_unused]] jobject request,\r
+                                                            jobject partialResult)\r
                 {\r
                     JUCE_CAMERA_LOG ("cameraCaptureSessionCaptureProgressed()");\r
 \r
-                    ignoreUnused (session, request);\r
-\r
                     if (isPreview)\r
                         updateState (partialResult);\r
                 }\r
 \r
-                void cameraCaptureSessionCaptureSequenceAborted (bool isPreview, jobject session, int sequenceId)\r
+                void cameraCaptureSessionCaptureSequenceAborted ([[maybe_unused]] bool isPreview,\r
+                                                                 [[maybe_unused]] jobject session,\r
+                                                                 [[maybe_unused]] int sequenceId)\r
                 {\r
                     JUCE_CAMERA_LOG ("cameraCaptureSessionCaptureSequenceAborted()");\r
-\r
-                    ignoreUnused (isPreview, isPreview, session, sequenceId);\r
                 }\r
 \r
-                void cameraCaptureSessionCaptureSequenceCompleted (bool isPreview, jobject session, int sequenceId, int64 frameNumber)\r
+                void cameraCaptureSessionCaptureSequenceCompleted ([[maybe_unused]] bool isPreview,\r
+                                                                   [[maybe_unused]] jobject session,\r
+                                                                   [[maybe_unused]] int sequenceId,\r
+                                                                   [[maybe_unused]] int64 frameNumber)\r
                 {\r
                     JUCE_CAMERA_LOG ("cameraCaptureSessionCaptureSequenceCompleted()");\r
-\r
-                    ignoreUnused (isPreview, session, sequenceId, frameNumber);\r
                 }\r
 \r
-                void cameraCaptureSessionCaptureStarted (bool isPreview, jobject session, jobject request, int64 timestamp, int64 frameNumber)\r
+                void cameraCaptureSessionCaptureStarted ([[maybe_unused]] bool isPreview,\r
+                                                         [[maybe_unused]] jobject session,\r
+                                                         [[maybe_unused]] jobject request,\r
+                                                         [[maybe_unused]] int64 timestamp,\r
+                                                         [[maybe_unused]] int64 frameNumber)\r
                 {\r
                     JUCE_CAMERA_LOG ("cameraCaptureSessionCaptureStarted()");\r
-\r
-                    ignoreUnused (isPreview, session, request, timestamp, frameNumber);\r
                 }\r
 \r
                 //==============================================================================\r
-                static void cameraCaptureSessionCaptureCompletedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult)\r
+                static void cameraCaptureSessionCaptureCompletedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult)\r
                 {\r
-                    if (auto* myself = reinterpret_cast<StillPictureTaker*> (host))\r
-                    {\r
-                        LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-                        LocalRef<jobject> request (getEnv()->NewLocalRef(rawRequest));\r
-                        LocalRef<jobject> result (getEnv()->NewLocalRef(rawResult));\r
+                    LocalRef<jobject> session (env->NewLocalRef (rawSession));\r
+                    LocalRef<jobject> request (env->NewLocalRef (rawRequest));\r
+                    LocalRef<jobject> result (env->NewLocalRef (rawResult));\r
 \r
-                        myself->cameraCaptureSessionCaptureCompleted (isPreview != 0, session, request, result);\r
-                    }\r
+                    t.cameraCaptureSessionCaptureCompleted (isPreview != 0, session, request, result);\r
                 }\r
 \r
-                static void cameraCaptureSessionCaptureFailedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult)\r
+                static void cameraCaptureSessionCaptureFailedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult)\r
                 {\r
-                    if (auto* myself = reinterpret_cast<StillPictureTaker*> (host))\r
-                    {\r
-                        LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-                        LocalRef<jobject> request (getEnv()->NewLocalRef(rawRequest));\r
-                        LocalRef<jobject> result (getEnv()->NewLocalRef(rawResult));\r
+                    LocalRef<jobject> session (env->NewLocalRef (rawSession));\r
+                    LocalRef<jobject> request (env->NewLocalRef (rawRequest));\r
+                    LocalRef<jobject> result (env->NewLocalRef (rawResult));\r
 \r
-                        myself->cameraCaptureSessionCaptureFailed (isPreview != 0, session, request, result);\r
-                    }\r
+                    t.cameraCaptureSessionCaptureFailed (isPreview != 0, session, request, result);\r
                 }\r
 \r
-                static void cameraCaptureSessionCaptureProgressedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult)\r
+                static void cameraCaptureSessionCaptureProgressedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jobject rawRequest, jobject rawResult)\r
                 {\r
-                    if (auto* myself = reinterpret_cast<StillPictureTaker*> (host))\r
-                    {\r
-                        LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-                        LocalRef<jobject> request (getEnv()->NewLocalRef(rawRequest));\r
-                        LocalRef<jobject> result (getEnv()->NewLocalRef(rawResult));\r
+                    LocalRef<jobject> session (env->NewLocalRef (rawSession));\r
+                    LocalRef<jobject> request (env->NewLocalRef (rawRequest));\r
+                    LocalRef<jobject> result (env->NewLocalRef (rawResult));\r
 \r
-                        myself->cameraCaptureSessionCaptureProgressed (isPreview != 0, session, request, result);\r
-                    }\r
+                    t.cameraCaptureSessionCaptureProgressed (isPreview != 0, session, request, result);\r
                 }\r
 \r
-                static void cameraCaptureSessionCaptureSequenceAbortedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jint sequenceId)\r
+                static void cameraCaptureSessionCaptureSequenceAbortedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jint sequenceId)\r
                 {\r
-                    if (auto* myself = reinterpret_cast<StillPictureTaker*> (host))\r
-                    {\r
-                        LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
+                    LocalRef<jobject> session (env->NewLocalRef (rawSession));\r
 \r
-                        myself->cameraCaptureSessionCaptureSequenceAborted (isPreview != 0, session, sequenceId);\r
-                    }\r
+                    t.cameraCaptureSessionCaptureSequenceAborted (isPreview != 0, session, sequenceId);\r
                 }\r
 \r
-                static void cameraCaptureSessionCaptureSequenceCompletedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jint sequenceId, jlong frameNumber)\r
+                static void cameraCaptureSessionCaptureSequenceCompletedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jint sequenceId, jlong frameNumber)\r
                 {\r
-                    if (auto* myself = reinterpret_cast<StillPictureTaker*> (host))\r
-                    {\r
-                        LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
+                    LocalRef<jobject> session (env->NewLocalRef (rawSession));\r
 \r
-                        myself->cameraCaptureSessionCaptureSequenceCompleted (isPreview != 0, session, sequenceId, frameNumber);\r
-                    }\r
+                    t.cameraCaptureSessionCaptureSequenceCompleted (isPreview != 0, session, sequenceId, frameNumber);\r
                 }\r
 \r
-                static void cameraCaptureSessionCaptureStartedCallback (JNIEnv*, jobject /*object*/, jlong host, jboolean isPreview, jobject rawSession, jobject rawRequest, jlong timestamp, jlong frameNumber)\r
+                static void cameraCaptureSessionCaptureStartedCallback (JNIEnv* env, StillPictureTaker& t, jboolean isPreview, jobject rawSession, jobject rawRequest, jlong timestamp, jlong frameNumber)\r
                 {\r
-                    if (auto* myself = reinterpret_cast<StillPictureTaker*> (host))\r
-                    {\r
-                        LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-                        LocalRef<jobject> request (getEnv()->NewLocalRef(rawRequest));\r
+                    LocalRef<jobject> session (env->NewLocalRef (rawSession));\r
+                    LocalRef<jobject> request (env->NewLocalRef (rawRequest));\r
 \r
-                        myself->cameraCaptureSessionCaptureStarted (isPreview != 0, session, request, timestamp, frameNumber);\r
-                    }\r
+                    t.cameraCaptureSessionCaptureStarted (isPreview != 0, session, request, timestamp, frameNumber);\r
                 }\r
             };\r
 \r
@@ -2120,11 +2096,11 @@ private:
             //==============================================================================\r
             #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK)    \\r
                 METHOD (constructor, "<init>", "(J)V") \\r
-                CALLBACK(cameraCaptureSessionActiveCallback,          "cameraCaptureSessionActive",          "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \\r
-                CALLBACK(cameraCaptureSessionClosedCallback,          "cameraCaptureSessionClosed",          "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \\r
-                CALLBACK(cameraCaptureSessionConfigureFailedCallback, "cameraCaptureSessionConfigureFailed", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \\r
-                CALLBACK(cameraCaptureSessionConfiguredCallback,      "cameraCaptureSessionConfigured",      "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \\r
-                CALLBACK(cameraCaptureSessionReadyCallback,           "cameraCaptureSessionReady",           "(JLandroid/hardware/camera2/CameraCaptureSession;)V")\r
+                CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionActiveCallback>,          "cameraCaptureSessionActive",          "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \\r
+                CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionClosedCallback>,          "cameraCaptureSessionClosed",          "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \\r
+                CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionConfigureFailedCallback>, "cameraCaptureSessionConfigureFailed", "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \\r
+                CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionConfiguredCallback>,      "cameraCaptureSessionConfigured",      "(JLandroid/hardware/camera2/CameraCaptureSession;)V") \\r
+                CALLBACK (generatedCallback<&CaptureSession::cameraCaptureSessionReadyCallback>,           "cameraCaptureSessionReady",           "(JLandroid/hardware/camera2/CameraCaptureSession;)V")\r
 \r
             DECLARE_JNI_CLASS_WITH_MIN_SDK (CameraCaptureSessionStateCallback, "com/rmsl/juce/CameraCaptureSessionStateCallback", 21)\r
             #undef JNI_CLASS_MEMBERS\r
@@ -2166,126 +2142,81 @@ private:
                 env->CallVoidMethod (captureRequestBuilder, CaptureRequestBuilder.set, jKey.get(), jValue.get());\r
             }\r
 \r
-            void cameraCaptureSessionActive (jobject session)\r
+            //==============================================================================\r
+            static void cameraCaptureSessionActiveCallback ([[maybe_unused]] JNIEnv* env,\r
+                                                            [[maybe_unused]] CaptureSession& t,\r
+                                                            [[maybe_unused]] jobject rawSession)\r
             {\r
                 JUCE_CAMERA_LOG ("cameraCaptureSessionActive()");\r
-                ignoreUnused (session);\r
             }\r
 \r
-            void cameraCaptureSessionClosed (jobject session)\r
+            static void cameraCaptureSessionClosedCallback ([[maybe_unused]] JNIEnv* env,\r
+                                                            CaptureSession& t,\r
+                                                            [[maybe_unused]] jobject rawSession)\r
             {\r
                 JUCE_CAMERA_LOG ("cameraCaptureSessionClosed()");\r
-                ignoreUnused (session);\r
 \r
-                closedEvent.signal();\r
+                t.closedEvent.signal();\r
             }\r
 \r
-            void cameraCaptureSessionConfigureFailed (jobject session)\r
+            static void cameraCaptureSessionConfigureFailedCallback ([[maybe_unused]] JNIEnv* env,\r
+                                                                     CaptureSession& t,\r
+                                                                     [[maybe_unused]] jobject rawSession)\r
             {\r
                 JUCE_CAMERA_LOG ("cameraCaptureSessionConfigureFailed()");\r
-                ignoreUnused (session);\r
 \r
-                MessageManager::callAsync ([weakRef = WeakReference<CaptureSession> { this }]\r
-                {\r
-                    if (weakRef != nullptr)\r
-                        weakRef->configuredCallback.captureSessionConfigured (nullptr);\r
-                });\r
+                MessageManager::callAsync ([weakRef = WeakReference<CaptureSession> { &t }]\r
+                                           {\r
+                                               if (weakRef != nullptr)\r
+                                                   weakRef->configuredCallback.captureSessionConfigured (nullptr);\r
+                                           });\r
             }\r
 \r
-            void cameraCaptureSessionConfigured (const LocalRef<jobject>& session)\r
+            static void cameraCaptureSessionConfiguredCallback (JNIEnv* env, CaptureSession& t, jobject rawSession)\r
             {\r
+                LocalRef<jobject> session (env->NewLocalRef (rawSession));\r
                 JUCE_CAMERA_LOG ("cameraCaptureSessionConfigured()");\r
 \r
-                if (pendingClose.get() == 1)\r
+                if (t.pendingClose.get() == 1)\r
                 {\r
                     // Already closing, bailout.\r
-                    closedEvent.signal();\r
+                    t.closedEvent.signal();\r
 \r
                     GlobalRef s (session);\r
 \r
                     MessageManager::callAsync ([s]()\r
-                        {\r
-                            getEnv()->CallVoidMethod (s, CameraCaptureSession.close);\r
-                        });\r
+                                               {\r
+                                                   getEnv()->CallVoidMethod (s, CameraCaptureSession.close);\r
+                                               });\r
 \r
                     return;\r
                 }\r
 \r
                 {\r
-                    const ScopedLock lock (captureSessionLock);\r
-                    captureSession = GlobalRef (session);\r
+                    const ScopedLock lock (t.captureSessionLock);\r
+                    t.captureSession = GlobalRef (session);\r
                 }\r
 \r
-                MessageManager::callAsync ([weakRef = WeakReference<CaptureSession> { this }]\r
-                {\r
-                    if (weakRef == nullptr)\r
-                        return;\r
+                MessageManager::callAsync ([weakRef = WeakReference<CaptureSession> { &t }]\r
+                                           {\r
+                                               if (weakRef == nullptr)\r
+                                                   return;\r
 \r
-                    weakRef->stillPictureTaker.reset (new StillPictureTaker (weakRef->captureSession,\r
-                                                                             weakRef->captureRequestBuilder,\r
-                                                                             weakRef->previewCaptureRequest,\r
-                                                                             weakRef->handler,\r
-                                                                             weakRef->autoFocusMode));\r
+                                               weakRef->stillPictureTaker.reset (new StillPictureTaker (weakRef->captureSession,\r
+                                                                                                        weakRef->captureRequestBuilder,\r
+                                                                                                        weakRef->previewCaptureRequest,\r
+                                                                                                        weakRef->handler,\r
+                                                                                                        weakRef->autoFocusMode));\r
 \r
-                    weakRef->configuredCallback.captureSessionConfigured (weakRef.get());\r
-                });\r
+                                               weakRef->configuredCallback.captureSessionConfigured (weakRef.get());\r
+                                           });\r
             }\r
 \r
-            void cameraCaptureSessionReady (const LocalRef<jobject>& session)\r
+            static void cameraCaptureSessionReadyCallback ([[maybe_unused]] JNIEnv* env,\r
+                                                           [[maybe_unused]] CaptureSession& t,\r
+                                                           [[maybe_unused]] jobject rawSession)\r
             {\r
                 JUCE_CAMERA_LOG ("cameraCaptureSessionReady()");\r
-                ignoreUnused (session);\r
-            }\r
-\r
-            //==============================================================================\r
-            static void cameraCaptureSessionActiveCallback (JNIEnv*, jobject, jlong host, jobject rawSession)\r
-            {\r
-                if (auto* myself = reinterpret_cast<CaptureSession*> (host))\r
-                {\r
-                    LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-\r
-                    myself->cameraCaptureSessionActive (session);\r
-                }\r
-            }\r
-\r
-            static void cameraCaptureSessionClosedCallback (JNIEnv*, jobject, jlong host, jobject rawSession)\r
-            {\r
-                if (auto* myself = reinterpret_cast<CaptureSession*> (host))\r
-                {\r
-                    LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-\r
-                    myself->cameraCaptureSessionClosed (session);\r
-                }\r
-            }\r
-\r
-            static void cameraCaptureSessionConfigureFailedCallback (JNIEnv*, jobject, jlong host, jobject rawSession)\r
-            {\r
-                if (auto* myself = reinterpret_cast<CaptureSession*> (host))\r
-                {\r
-                    LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-\r
-                    myself->cameraCaptureSessionConfigureFailed (session);\r
-                }\r
-            }\r
-\r
-            static void cameraCaptureSessionConfiguredCallback (JNIEnv*, jobject, jlong host, jobject rawSession)\r
-            {\r
-                if (auto* myself = reinterpret_cast<CaptureSession*> (host))\r
-                {\r
-                    LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-\r
-                    myself->cameraCaptureSessionConfigured (session);\r
-                }\r
-            }\r
-\r
-            static void cameraCaptureSessionReadyCallback (JNIEnv*, jobject, jlong host, jobject rawSession)\r
-            {\r
-                if (auto* myself = reinterpret_cast<CaptureSession*> (host))\r
-                {\r
-                    LocalRef<jobject> session (getEnv()->NewLocalRef(rawSession));\r
-\r
-                    myself->cameraCaptureSessionReady (session);\r
-                }\r
             }\r
 \r
             //==============================================================================\r
@@ -2383,10 +2314,10 @@ private:
         //==============================================================================\r
         #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK)    \\r
             METHOD (constructor, "<init>", "(J)V") \\r
-            CALLBACK (cameraDeviceStateClosedCallback,       "cameraDeviceStateClosed",       "(JLandroid/hardware/camera2/CameraDevice;)V")  \\r
-            CALLBACK (cameraDeviceStateDisconnectedCallback, "cameraDeviceStateDisconnected", "(JLandroid/hardware/camera2/CameraDevice;)V")  \\r
-            CALLBACK (cameraDeviceStateErrorCallback,        "cameraDeviceStateError",        "(JLandroid/hardware/camera2/CameraDevice;I)V") \\r
-            CALLBACK (cameraDeviceStateOpenedCallback,       "cameraDeviceStateOpened",       "(JLandroid/hardware/camera2/CameraDevice;)V")\r
+            CALLBACK (generatedCallback<&ScopedCameraDevice::cameraDeviceStateClosedCallback>,       "cameraDeviceStateClosed",       "(JLandroid/hardware/camera2/CameraDevice;)V")  \\r
+            CALLBACK (generatedCallback<&ScopedCameraDevice::cameraDeviceStateDisconnectedCallback>, "cameraDeviceStateDisconnected", "(JLandroid/hardware/camera2/CameraDevice;)V")  \\r
+            CALLBACK (generatedCallback<&ScopedCameraDevice::cameraDeviceStateErrorCallback>,        "cameraDeviceStateError",        "(JLandroid/hardware/camera2/CameraDevice;I)V") \\r
+            CALLBACK (generatedCallback<&ScopedCameraDevice::cameraDeviceStateOpenedCallback>,       "cameraDeviceStateOpened",       "(JLandroid/hardware/camera2/CameraDevice;)V")\r
 \r
         DECLARE_JNI_CLASS_WITH_MIN_SDK (CameraDeviceStateCallback, "com/rmsl/juce/CameraDeviceStateCallback", 21)\r
         #undef JNI_CLASS_MEMBERS\r
@@ -2399,92 +2330,66 @@ private:
         }\r
 \r
         //==============================================================================\r
-        void cameraDeviceStateClosed()\r
+        void notifyOpenResult()\r
+        {\r
+            MessageManager::callAsync ([this]() { owner.cameraOpenFinished (openError); });\r
+        }\r
+\r
+        //==============================================================================\r
+        static void cameraDeviceStateClosedCallback (JNIEnv*, ScopedCameraDevice& s, jobject)\r
         {\r
             JUCE_CAMERA_LOG ("cameraDeviceStateClosed()");\r
 \r
-            closedEvent.signal();\r
+            s.closedEvent.signal();\r
         }\r
 \r
-        void cameraDeviceStateDisconnected()\r
+        static void cameraDeviceStateDisconnectedCallback (JNIEnv*, ScopedCameraDevice& s, jobject)\r
         {\r
             JUCE_CAMERA_LOG ("cameraDeviceStateDisconnected()");\r
 \r
-            if (pendingOpen.compareAndSetBool (0, 1))\r
+            if (s.pendingOpen.compareAndSetBool (0, 1))\r
             {\r
-                openError = "Device disconnected";\r
+                s.openError = "Device disconnected";\r
 \r
-                notifyOpenResult();\r
+                s.notifyOpenResult();\r
             }\r
 \r
-            MessageManager::callAsync ([this]() { close(); });\r
+            MessageManager::callAsync ([&s] { s.close(); });\r
         }\r
 \r
-        void cameraDeviceStateError (int errorCode)\r
+        static void cameraDeviceStateErrorCallback (JNIEnv*, ScopedCameraDevice& s, jobject, jint errorCode)\r
         {\r
-            String error = cameraErrorCodeToString (errorCode);\r
+            auto error = cameraErrorCodeToString (errorCode);\r
 \r
             JUCE_CAMERA_LOG ("cameraDeviceStateError(), error: " + error);\r
 \r
-            if (pendingOpen.compareAndSetBool (0, 1))\r
+            if (s.pendingOpen.compareAndSetBool (0, 1))\r
             {\r
-                openError = error;\r
+                s.openError = error;\r
 \r
-                notifyOpenResult();\r
+                s.notifyOpenResult();\r
             }\r
 \r
-            fatalErrorOccurred.set (1);\r
+            s.fatalErrorOccurred.set (1);\r
 \r
-            MessageManager::callAsync ([this, error]()\r
+            MessageManager::callAsync ([&s, error]()\r
                                        {\r
-                                           owner.cameraDeviceError (error);\r
-                                           close();\r
+                                           s.owner.cameraDeviceError (error);\r
+                                           s.close();\r
                                        });\r
         }\r
 \r
-        void cameraDeviceStateOpened (const LocalRef<jobject>& cameraDeviceToUse)\r
+        static void cameraDeviceStateOpenedCallback (JNIEnv* env, ScopedCameraDevice& s, jobject cameraDeviceToUse)\r
         {\r
             JUCE_CAMERA_LOG ("cameraDeviceStateOpened()");\r
 \r
-            pendingOpen.set (0);\r
-\r
-            cameraDevice = GlobalRef (cameraDeviceToUse);\r
-\r
-            notifyOpenResult();\r
-        }\r
-\r
-        void notifyOpenResult()\r
-        {\r
-            MessageManager::callAsync ([this]() { owner.cameraOpenFinished (openError); });\r
-        }\r
-\r
-        //==============================================================================\r
-        static void JNICALL cameraDeviceStateClosedCallback (JNIEnv*, jobject, jlong host, jobject)\r
-        {\r
-            if (auto* myself = reinterpret_cast<ScopedCameraDevice*>(host))\r
-                myself->cameraDeviceStateClosed();\r
-        }\r
+            LocalRef<jobject> camera (env->NewLocalRef (cameraDeviceToUse));\r
 \r
-        static void JNICALL cameraDeviceStateDisconnectedCallback (JNIEnv*, jobject, jlong host, jobject)\r
-        {\r
-            if (auto* myself = reinterpret_cast<ScopedCameraDevice*>(host))\r
-                myself->cameraDeviceStateDisconnected();\r
-        }\r
-\r
-        static void JNICALL cameraDeviceStateErrorCallback (JNIEnv*, jobject, jlong host, jobject, jint error)\r
-        {\r
-            if (auto* myself = reinterpret_cast<ScopedCameraDevice*>(host))\r
-                myself->cameraDeviceStateError (error);\r
-        }\r
+            s.pendingOpen.set (0);\r
 \r
-        static void JNICALL cameraDeviceStateOpenedCallback (JNIEnv*, jobject, jlong host, jobject rawCamera)\r
-        {\r
-            if (auto* myself = reinterpret_cast<ScopedCameraDevice*>(host))\r
-            {\r
-                LocalRef<jobject> camera(getEnv()->NewLocalRef(rawCamera));\r
+            s.cameraDevice = GlobalRef (camera);\r
 \r
-                myself->cameraDeviceStateOpened (camera);\r
-            }\r
+            s.notifyOpenResult();\r
         }\r
     };\r
 \r
@@ -2824,7 +2729,7 @@ private:
             METHOD (constructor,          "<init>",               "(JLandroid/content/Context;I)V") \\r
             METHOD (disable,              "disable",              "()V") \\r
             METHOD (enable,               "enable",               "()V") \\r
-            CALLBACK (deviceOrientationChanged, "deviceOrientationChanged", "(JI)V")\r
+            CALLBACK (generatedCallback<&DeviceOrientationChangeListener::orientationChanged>, "deviceOrientationChanged", "(JI)V")\r
 \r
         DECLARE_JNI_CLASS_WITH_MIN_SDK (OrientationEventListener, "com/rmsl/juce/JuceOrientationEventListener", 21)\r
         #undef JNI_CLASS_MEMBERS\r
@@ -2839,7 +2744,7 @@ private:
         }\r
 \r
         //==============================================================================\r
-        void orientationChanged (int orientation)\r
+        static void orientationChanged (JNIEnv*, DeviceOrientationChangeListener& t, jint orientation)\r
         {\r
             jassert (orientation < 360);\r
 \r
@@ -2847,25 +2752,31 @@ private:
             if (orientation < 0)\r
                 return;\r
 \r
-            auto oldOrientation = deviceOrientation;\r
+            const auto oldOrientation = t.deviceOrientation;\r
+\r
+            t.deviceOrientation = [orientation]\r
+            {\r
+                if (orientation > (360 - 45) || orientation < 45)\r
+                    return Desktop::upright;\r
+\r
+                if (orientation < 135)\r
+                    return Desktop::rotatedClockwise;\r
+\r
+                if (orientation < 225)\r
+                    return Desktop::upsideDown;\r
+\r
+                return Desktop::rotatedAntiClockwise;\r
+            }();\r
 \r
             // NB: this assumes natural position to be portrait always, but some devices may be landscape...\r
-            if (orientation > (360 - 45) || orientation < 45)\r
-                deviceOrientation = Desktop::upright;\r
-            else if (orientation < 135)\r
-                deviceOrientation = Desktop::rotatedClockwise;\r
-            else if (orientation < 225)\r
-                deviceOrientation = Desktop::upsideDown;\r
-            else\r
-                deviceOrientation = Desktop::rotatedAntiClockwise;\r
 \r
-            if (oldOrientation != deviceOrientation)\r
+            if (oldOrientation != t.deviceOrientation)\r
             {\r
-                lastKnownScreenOrientation = Desktop::getInstance().getCurrentOrientation();\r
+                t.lastKnownScreenOrientation = Desktop::getInstance().getCurrentOrientation();\r
 \r
                 // Need to update preview transform, but screen orientation will change slightly\r
                 // later than sensor orientation.\r
-                startTimer (500);\r
+                t.startTimer (500);\r
             }\r
         }\r
 \r
@@ -2890,12 +2801,6 @@ private:
                 numChecksForOrientationChange = 10;\r
             }\r
         }\r
-\r
-        static void deviceOrientationChanged (JNIEnv*, jobject /*obj*/, jlong host, jint orientation)\r
-        {\r
-            if (auto* myself = reinterpret_cast<DeviceOrientationChangeListener*> (host))\r
-                myself->orientationChanged (orientation);\r
-        }\r
     };\r
 \r
     //==============================================================================\r
@@ -3189,7 +3094,7 @@ private:
     {\r
         auto* env = getEnv();\r
 \r
-        auto quitSafelyMethod = env->GetMethodID(AndroidHandlerThread, "quitSafely", "()Z");\r
+        auto quitSafelyMethod = env->GetMethodID (AndroidHandlerThread, "quitSafely", "()Z");\r
 \r
         // this code will only run on SDK >= 21\r
         jassert(quitSafelyMethod != nullptr);\r
@@ -3277,9 +3182,3 @@ String CameraDevice::getFileExtension()
 {\r
     return ".mp4";\r
 }\r
-\r
-//==============================================================================\r
-CameraDevice::Pimpl::ScopedCameraDevice::CaptureSession::StillPictureTaker::CameraCaptureSessionCaptureCallback_Class CameraDevice::Pimpl::ScopedCameraDevice::CaptureSession::StillPictureTaker::CameraCaptureSessionCaptureCallback;\r
-CameraDevice::Pimpl::ScopedCameraDevice::CameraDeviceStateCallback_Class CameraDevice::Pimpl::ScopedCameraDevice::CameraDeviceStateCallback;\r
-CameraDevice::Pimpl::ScopedCameraDevice::CaptureSession::CameraCaptureSessionStateCallback_Class CameraDevice::Pimpl::ScopedCameraDevice::CaptureSession::CameraCaptureSessionStateCallback;\r
-CameraDevice::Pimpl::DeviceOrientationChangeListener::OrientationEventListener_Class CameraDevice::Pimpl::DeviceOrientationChangeListener::OrientationEventListener;\r
index 101bf958fcf13b2bca8312eec664b55a35bc5b10..56d94bbb9a8856e4f84cc74dfa0a2447584478e7 100644 (file)
@@ -32,7 +32,7 @@
 //\r
 // files with min sdk version 21\r
 // See juce_core/native/java/README.txt on how to generate this byte-code.\r
-static const unsigned char MediaSessionByteCode[] =\r
+static const uint8 MediaSessionByteCode[] =\r
 { 31,139,8,8,247,108,161,94,0,3,77,101,100,105,97,83,101,115,115,105,111,110,66,121,116,101,67,111,100,101,46,100,101,120,0,149,\r
 152,127,108,28,71,21,199,223,236,253,180,207,190,95,254,221,186,169,211,56,137,19,234,220,145,26,226,228,28,99,199,216,196,233,\r
 249,71,125,182,107,76,168,187,246,109,236,77,238,118,143,221,189,171,45,132,168,170,32,21,209,63,144,74,165,170,82,81,144,64,\r
@@ -757,12 +757,12 @@ private:
             //==============================================================================\r
             #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
                 METHOD (constructor, "<init>", "(J)V")                  \\r
-                CALLBACK (audioInfoChanged,     "mediaControllerAudioInfoChanged",      "(JLandroid/media/session/MediaController$PlaybackInfo;)V") \\r
-                CALLBACK (metadataChanged,      "mediaControllerMetadataChanged",       "(JLandroid/media/MediaMetadata;)V") \\r
-                CALLBACK (playbackStateChanged, "mediaControllerPlaybackStateChanged",  "(JLandroid/media/session/PlaybackState;)V") \\r
-                CALLBACK (sessionDestroyed,     "mediaControllerSessionDestroyed",      "(J)V")\r
+                CALLBACK (generatedCallback<&Controller::audioInfoChanged>,     "mediaControllerAudioInfoChanged",      "(JLandroid/media/session/MediaController$PlaybackInfo;)V") \\r
+                CALLBACK (generatedCallback<&Controller::metadataChanged>,      "mediaControllerMetadataChanged",       "(JLandroid/media/MediaMetadata;)V") \\r
+                CALLBACK (generatedCallback<&Controller::playbackStateChanged>, "mediaControllerPlaybackStateChanged",  "(JLandroid/media/session/PlaybackState;)V") \\r
+                CALLBACK (generatedCallback<&Controller::sessionDestroyed>,     "mediaControllerSessionDestroyed",      "(J)V")\r
 \r
-            DECLARE_JNI_CLASS_WITH_BYTECODE (AndroidMediaControllerCallback, "com/rmsl/juce/MediaControllerCallback", 21, MediaSessionByteCode, sizeof (MediaSessionByteCode))\r
+            DECLARE_JNI_CLASS_WITH_BYTECODE (AndroidMediaControllerCallback, "com/rmsl/juce/MediaControllerCallback", 21, MediaSessionByteCode)\r
            #undef JNI_CLASS_MEMBERS\r
 \r
             LocalRef<jobject> createControllerCallbacks()\r
@@ -774,34 +774,24 @@ private:
 \r
             //==============================================================================\r
             // MediaSessionController callbacks\r
-            static void audioInfoChanged (JNIEnv*, jobject, jlong host, jobject playbackInfo)\r
+            static void audioInfoChanged (JNIEnv*, [[maybe_unused]] Controller& t, [[maybe_unused]] jobject playbackInfo)\r
             {\r
-                if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession::Controller*> (host))\r
-                {\r
-                    ignoreUnused (playbackInfo);\r
-                    JUCE_VIDEO_LOG ("MediaSessionController::audioInfoChanged()");\r
-                }\r
+                JUCE_VIDEO_LOG ("MediaSessionController::audioInfoChanged()");\r
             }\r
 \r
-            static void metadataChanged (JNIEnv*, jobject, jlong host, jobject metadata)\r
+            static void metadataChanged (JNIEnv*, [[maybe_unused]] Controller&, [[maybe_unused]] jobject metadata)\r
             {\r
-                if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession::Controller*> (host))\r
-                {\r
-                    ignoreUnused (metadata);\r
-                    JUCE_VIDEO_LOG ("MediaSessionController::metadataChanged()");\r
-                }\r
+                JUCE_VIDEO_LOG ("MediaSessionController::metadataChanged()");\r
             }\r
 \r
-            static void playbackStateChanged (JNIEnv*, jobject, jlong host, jobject state)\r
+            static void playbackStateChanged (JNIEnv*, Controller& t, [[maybe_unused]] jobject state)\r
             {\r
-                if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession::Controller*> (host))\r
-                    myself->stateChanged (state);\r
+                t.stateChanged (state);\r
             }\r
 \r
-            static void sessionDestroyed (JNIEnv*, jobject, jlong host)\r
+            static void sessionDestroyed (JNIEnv*, [[maybe_unused]] Controller& t)\r
             {\r
-                if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession::Controller*> (host))\r
-                    JUCE_VIDEO_LOG ("MediaSessionController::sessionDestroyed()");\r
+                JUCE_VIDEO_LOG ("MediaSessionController::sessionDestroyed()");\r
             }\r
         };\r
 \r
@@ -835,10 +825,8 @@ private:
                     getEnv()->CallVoidMethod (nativeMediaPlayer, AndroidMediaPlayer.setDisplay, videoSurfaceHolder.get());\r
             }\r
 \r
-            void load (const LocalRef<jstring>& mediaId, const LocalRef<jobject>& extras)\r
+            void load (const LocalRef<jstring>& mediaId, [[maybe_unused]] const LocalRef<jobject>& extras)\r
             {\r
-                ignoreUnused (extras);\r
-\r
                 closeVideo();\r
 \r
                 auto* env = getEnv();\r
@@ -1114,39 +1102,31 @@ private:
             State currentState = State::idle;\r
 \r
             //==============================================================================\r
-            void onPrepared (LocalRef<jobject>& mediaPlayer) override\r
+            void onPrepared ([[maybe_unused]] LocalRef<jobject>& mediaPlayer) override\r
             {\r
                 JUCE_VIDEO_LOG ("MediaPlayer::onPrepared()");\r
 \r
-                ignoreUnused (mediaPlayer);\r
-\r
                 currentState = State::prepared;\r
 \r
                 owner.playerPrepared();\r
             }\r
 \r
-            void onBufferingUpdate (LocalRef<jobject>& mediaPlayer, int progress) override\r
+            void onBufferingUpdate ([[maybe_unused]] LocalRef<jobject>& mediaPlayer, int progress) override\r
             {\r
-                ignoreUnused (mediaPlayer);\r
-\r
                 owner.playerBufferingUpdated (progress);\r
             }\r
 \r
-            void onSeekComplete (LocalRef<jobject>& mediaPlayer) override\r
+            void onSeekComplete ([[maybe_unused]] LocalRef<jobject>& mediaPlayer) override\r
             {\r
                 JUCE_VIDEO_LOG ("MediaPlayer::onSeekComplete()");\r
 \r
-                ignoreUnused (mediaPlayer);\r
-\r
                 owner.playerSeekCompleted();\r
             }\r
 \r
-            void onCompletion (LocalRef<jobject>& mediaPlayer) override\r
+            void onCompletion ([[maybe_unused]] LocalRef<jobject>& mediaPlayer) override\r
             {\r
                 JUCE_VIDEO_LOG ("MediaPlayer::onCompletion()");\r
 \r
-                ignoreUnused (mediaPlayer);\r
-\r
                 currentState = State::complete;\r
 \r
                 owner.playerPlaybackCompleted();\r
@@ -1169,13 +1149,11 @@ private:
                 MEDIA_INFO_SUBTITLE_TIMED_OUT    = 902\r
             };\r
 \r
-            bool onInfo (LocalRef<jobject>& mediaPlayer, int what, int extra) override\r
+            bool onInfo ([[maybe_unused]] LocalRef<jobject>& mediaPlayer, int what, [[maybe_unused]] int extra) override\r
             {\r
                 JUCE_VIDEO_LOG ("MediaPlayer::onInfo(), infoCode: " + String (what) + " (" + infoCodeToString (what) + ")"\r
                                 + ", extraCode: " + String (extra));\r
 \r
-                ignoreUnused (mediaPlayer, extra);\r
-\r
                 if (what == MEDIA_INFO_BUFFERING_START)\r
                     owner.playerBufferingStarted();\r
                 else if (what == MEDIA_INFO_BUFFERING_END)\r
@@ -1205,7 +1183,7 @@ private:
                 }\r
             }\r
 \r
-            bool onError (LocalRef<jobject>& mediaPlayer, int what, int extra) override\r
+            bool onError ([[maybe_unused]] LocalRef<jobject>& mediaPlayer, int what, int extra) override\r
             {\r
                 auto errorMessage = errorCodeToString (what);\r
                 auto extraMessage = errorCodeToString (extra);\r
@@ -1216,8 +1194,6 @@ private:
                 JUCE_VIDEO_LOG ("MediaPlayer::onError(), errorCode: " + String (what) + " (" + errorMessage + ")"\r
                                 + ", extraCode: " + String (extra) + " (" + extraMessage + ")");\r
 \r
-                ignoreUnused (mediaPlayer);\r
-\r
                 currentState = State::error;\r
 \r
                 owner.errorOccurred (errorMessage);\r
@@ -1295,11 +1271,11 @@ private:
         //==============================================================================\r
         #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
             METHOD (constructor, "<init>", "(J)V")                      \\r
-            CALLBACK (pauseCallback,           "mediaSessionPause",           "(J)V") \\r
-            CALLBACK (playCallback,            "mediaSessionPlay",            "(J)V") \\r
-            CALLBACK (playFromMediaIdCallback, "mediaSessionPlayFromMediaId", "(JLjava/lang/String;Landroid/os/Bundle;)V") \\r
-            CALLBACK (seekToCallback,          "mediaSessionSeekTo",          "(JJ)V") \\r
-            CALLBACK (stopCallback,            "mediaSessionStop",            "(J)V")\r
+            CALLBACK (generatedCallback<&MediaSession::pauseCallback>,           "mediaSessionPause",           "(J)V") \\r
+            CALLBACK (generatedCallback<&MediaSession::playCallback>,            "mediaSessionPlay",            "(J)V") \\r
+            CALLBACK (generatedCallback<&MediaSession::playFromMediaIdCallback>, "mediaSessionPlayFromMediaId", "(JLjava/lang/String;Landroid/os/Bundle;)V") \\r
+            CALLBACK (generatedCallback<&MediaSession::seekToCallback>,          "mediaSessionSeekTo",          "(JJ)V") \\r
+            CALLBACK (generatedCallback<&MediaSession::stopCallback>,            "mediaSessionStop",            "(J)V")\r
 \r
         DECLARE_JNI_CLASS_WITH_MIN_SDK (AndroidMediaSessionCallback, "com/rmsl/juce/MediaSessionCallback", 21)\r
         #undef JNI_CLASS_MEMBERS\r
@@ -1313,78 +1289,62 @@ private:
 \r
         //==============================================================================\r
         // MediaSession callbacks\r
-        static void pauseCallback (JNIEnv*, jobject, jlong host)\r
+        static void pauseCallback (JNIEnv*, MediaSession& t)\r
         {\r
-            if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession*> (host))\r
-            {\r
-                JUCE_VIDEO_LOG ("MediaSession::pauseCallback()");\r
-                myself->player.pause();\r
-                myself->updatePlaybackState();\r
-\r
-                myself->abandonAudioFocus();\r
-            }\r
+            JUCE_VIDEO_LOG ("MediaSession::pauseCallback()");\r
+            t.player.pause();\r
+            t.updatePlaybackState();\r
+            t.abandonAudioFocus();\r
         }\r
 \r
-        static void playCallback (JNIEnv*, jobject, jlong host)\r
+        static void playCallback (JNIEnv* env, MediaSession& t)\r
         {\r
-            if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession*> (host))\r
-            {\r
-                JUCE_VIDEO_LOG ("MediaSession::playCallback()");\r
+            JUCE_VIDEO_LOG ("MediaSession::playCallback()");\r
 \r
-                myself->requestAudioFocus();\r
+            t.requestAudioFocus();\r
 \r
-                if (! myself->hasAudioFocus)\r
-                {\r
-                    myself->errorOccurred ("Application has been denied audio focus. Try again later.");\r
-                    return;\r
-                }\r
+            if (! t.hasAudioFocus)\r
+            {\r
+                t.errorOccurred ("Application has been denied audio focus. Try again later.");\r
+                return;\r
+            }\r
 \r
-                getEnv()->CallVoidMethod (myself->nativeMediaSession, AndroidMediaSession.setActive, true);\r
+            env->CallVoidMethod (t.nativeMediaSession, AndroidMediaSession.setActive, true);\r
 \r
-                myself->player.play();\r
-                myself->setSpeed (myself->playSpeedMult);\r
-                myself->updatePlaybackState();\r
-            }\r
+            t.player.play();\r
+            t.setSpeed (t.playSpeedMult);\r
+            t.updatePlaybackState();\r
         }\r
 \r
-        static void playFromMediaIdCallback (JNIEnv* env, jobject, jlong host, jstring mediaId, jobject extras)\r
+        static void playFromMediaIdCallback (JNIEnv* env, MediaSession& t, jstring mediaId, jobject extras)\r
         {\r
-            if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession*> (host))\r
-            {\r
-                JUCE_VIDEO_LOG ("MediaSession::playFromMediaIdCallback()");\r
+            JUCE_VIDEO_LOG ("MediaSession::playFromMediaIdCallback()");\r
 \r
-                myself->player.load (LocalRef<jstring> ((jstring) env->NewLocalRef(mediaId)), LocalRef<jobject> (env->NewLocalRef(extras)));\r
-                myself->updatePlaybackState();\r
-            }\r
+            t.player.load (LocalRef<jstring> ((jstring) env->NewLocalRef (mediaId)), LocalRef<jobject> (env->NewLocalRef (extras)));\r
+            t.updatePlaybackState();\r
         }\r
 \r
-        static void seekToCallback (JNIEnv* /*env*/, jobject, jlong host, jlong pos)\r
+        static void seekToCallback (JNIEnv*, MediaSession& t, jlong pos)\r
         {\r
-            if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession*> (host))\r
-            {\r
-                JUCE_VIDEO_LOG ("MediaSession::seekToCallback()");\r
+            JUCE_VIDEO_LOG ("MediaSession::seekToCallback()");\r
 \r
-                myself->pendingSeekRequest = true;\r
-                myself->player.setPlayPosition ((jint) pos);\r
-                myself->updatePlaybackState();\r
-            }\r
+            t.pendingSeekRequest = true;\r
+            t.player.setPlayPosition ((jint) pos);\r
+            t.updatePlaybackState();\r
         }\r
 \r
-        static void stopCallback(JNIEnv* env, jobject, jlong host)\r
+        static void stopCallback (JNIEnv* env, MediaSession& t)\r
         {\r
-            if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::MediaSession*> (host))\r
-            {\r
-                JUCE_VIDEO_LOG ("MediaSession::stopCallback()");\r
+            JUCE_VIDEO_LOG ("MediaSession::stopCallback()");\r
 \r
-                env->CallVoidMethod (myself->nativeMediaSession, AndroidMediaSession.setActive, false);\r
+            env->CallVoidMethod (t.nativeMediaSession, AndroidMediaSession.setActive, false);\r
 \r
-                myself->player.closeVideo();\r
-                myself->updatePlaybackState();\r
+            t.player.closeVideo();\r
+            t.updatePlaybackState();\r
 \r
-                myself->abandonAudioFocus();\r
+            t.abandonAudioFocus();\r
 \r
-                myself->owner.closeVideoFinished();\r
-            }\r
+            t.owner.closeVideoFinished();\r
         }\r
 \r
         //==============================================================================\r
@@ -1689,7 +1649,7 @@ private:
         #define JNI_CLASS_MEMBERS(METHOD, STATICMETHOD, FIELD, STATICFIELD, CALLBACK) \\r
             METHOD (constructor, "<init>",     "(Landroid/app/Activity;J)V") \\r
             METHOD (setEnabled,  "setEnabled", "(Z)V")                  \\r
-            CALLBACK (systemVolumeChangedCallback, "mediaSessionSystemVolumeChanged", "(J)V")\r
+            CALLBACK (generatedCallback<&SystemVolumeListener::systemVolumeChanged>, "mediaSessionSystemVolumeChanged", "(J)V")\r
 \r
         DECLARE_JNI_CLASS_WITH_MIN_SDK (SystemVolumeObserver, "com/rmsl/juce/SystemVolumeObserver", 21)\r
         #undef JNI_CLASS_MEMBERS\r
@@ -1709,14 +1669,14 @@ private:
 \r
             // Send first notification instantly to ensure sync.\r
             if (shouldBeEnabled)\r
-                systemVolumeChanged();\r
+                systemVolumeChanged (getEnv(), *this);\r
         }\r
 \r
     private:\r
         //==============================================================================\r
-        void systemVolumeChanged()\r
+        static void systemVolumeChanged (JNIEnv*, SystemVolumeListener& t)\r
         {\r
-            MessageManager::callAsync ([weakThis = WeakReference<SystemVolumeListener> { this }]() mutable\r
+            MessageManager::callAsync ([weakThis = WeakReference<SystemVolumeListener> { &t }]\r
                                        {\r
                                            if (weakThis == nullptr)\r
                                                return;\r
@@ -1727,13 +1687,6 @@ private:
 \r
         }\r
 \r
-        //==============================================================================\r
-        static void systemVolumeChangedCallback (JNIEnv*, jobject, jlong host)\r
-        {\r
-            if (auto* myself = reinterpret_cast<VideoComponent::Pimpl::SystemVolumeListener*> (host))\r
-                myself->systemVolumeChanged();\r
-        }\r
-\r
         JUCE_DECLARE_WEAK_REFERENCEABLE (SystemVolumeListener)\r
     };\r
 \r
@@ -1845,8 +1798,3 @@ private:
 \r
 //==============================================================================\r
 constexpr VideoComponent::Pimpl::MediaSession::Player::StateInfo VideoComponent::Pimpl::MediaSession::Player::stateInfos[];\r
-\r
-//==============================================================================\r
-VideoComponent::Pimpl::MediaSession::AndroidMediaSessionCallback_Class VideoComponent::Pimpl::MediaSession::AndroidMediaSessionCallback;\r
-VideoComponent::Pimpl::MediaSession::Controller::AndroidMediaControllerCallback_Class VideoComponent::Pimpl::MediaSession::Controller::AndroidMediaControllerCallback;\r
-VideoComponent::Pimpl::SystemVolumeListener::SystemVolumeObserver_Class VideoComponent::Pimpl::SystemVolumeListener::SystemVolumeObserver;\r
index 97a48c5a2a46f1fc3cbcd2192128c66fec814030..d5b8187206ef80125a149b072546646bf447e63d 100644 (file)
@@ -524,23 +524,19 @@ private:
 \r
         private:\r
             //==============================================================================\r
-            static void started (id self, SEL, NSNotification* notification)\r
+            static void started (id self, SEL, [[maybe_unused]] NSNotification* notification)\r
             {\r
                 JUCE_CAMERA_LOG (nsStringToJuce ([notification description]));\r
 \r
-                ignoreUnused (notification);\r
-\r
                 dispatch_async (dispatch_get_main_queue(),\r
                                 ^{\r
                                     getOwner (self).cameraSessionStarted();\r
                                 });\r
             }\r
 \r
-            static void stopped (id, SEL, NSNotification* notification)\r
+            static void stopped (id, SEL, [[maybe_unused]] NSNotification* notification)\r
             {\r
                 JUCE_CAMERA_LOG (nsStringToJuce ([notification description]));\r
-\r
-                ignoreUnused (notification);\r
             }\r
 \r
             static void runtimeError (id self, SEL, NSNotification* notification)\r
@@ -555,18 +551,14 @@ private:
                                 });\r
             }\r
 \r
-            static void interrupted (id, SEL, NSNotification* notification)\r
+            static void interrupted (id, SEL, [[maybe_unused]] NSNotification* notification)\r
             {\r
                 JUCE_CAMERA_LOG (nsStringToJuce ([notification description]));\r
-\r
-                ignoreUnused (notification);\r
             }\r
 \r
-            static void interruptionEnded (id, SEL, NSNotification* notification)\r
+            static void interruptionEnded (id, SEL, [[maybe_unused]] NSNotification* notification)\r
             {\r
                 JUCE_CAMERA_LOG (nsStringToJuce ([notification description]));\r
-\r
-                ignoreUnused (notification);\r
             }\r
         };\r
 \r
@@ -788,8 +780,7 @@ private:
 \r
                 static void didFinishCaptureForSettings (id, SEL, AVCapturePhotoOutput*, AVCaptureResolvedPhotoSettings*, NSError* error)\r
                 {\r
-                    String errorString = error != nil ? nsStringToJuce (error.localizedDescription) : String();\r
-                    ignoreUnused (errorString);\r
+                    [[maybe_unused]] String errorString = error != nil ? nsStringToJuce (error.localizedDescription) : String();\r
 \r
                     JUCE_CAMERA_LOG ("didFinishCaptureForSettings(), error = " + errorString);\r
                 }\r
@@ -799,8 +790,7 @@ private:
                 {\r
                     getOwner (self).takingPicture = false;\r
 \r
-                    String errorString = error != nil ? nsStringToJuce (error.localizedDescription) : String();\r
-                    ignoreUnused (errorString);\r
+                    [[maybe_unused]] String errorString = error != nil ? nsStringToJuce (error.localizedDescription) : String();\r
 \r
                     JUCE_CAMERA_LOG ("didFinishProcessingPhoto(), error = " + errorString);\r
 \r
@@ -904,8 +894,7 @@ private:
                 {\r
                     getOwner (self).takingPicture = false;\r
 \r
-                    String errorString = error != nil ? nsStringToJuce (error.localizedDescription) : String();\r
-                    ignoreUnused (errorString);\r
+                    [[maybe_unused]] String errorString = error != nil ? nsStringToJuce (error.localizedDescription) : String();\r
 \r
                     JUCE_CAMERA_LOG ("didFinishProcessingPhotoSampleBuffer(), error = " + errorString);\r
 \r
@@ -1019,10 +1008,8 @@ private:
             }\r
 \r
         private:\r
-            static void printVideoOutputDebugInfo (AVCaptureMovieFileOutput* output)\r
+            static void printVideoOutputDebugInfo ([[maybe_unused]] AVCaptureMovieFileOutput* output)\r
             {\r
-                ignoreUnused (output);\r
-\r
                 JUCE_CAMERA_LOG ("Available video codec types:");\r
 \r
                #if JUCE_CAMERA_LOG_ENABLED\r
index 28748f8de2eafe13456b485b6fbff90ad91f71e8..6280e56fb7d14e2c38d22092d62ee7893dbd2575 100644 (file)
@@ -306,8 +306,7 @@ private:
             {\r
                 if (error != nil)\r
                 {\r
-                    String errorString = error != nil ? nsStringToJuce (error.localizedDescription) : String();\r
-                    ignoreUnused (errorString);\r
+                    [[maybe_unused]] String errorString = error != nil ? nsStringToJuce (error.localizedDescription) : String();\r
 \r
                     JUCE_CAMERA_LOG ("Still picture capture failed, error: " + errorString);\r
                     jassertfalse;\r
index 9ba11f4e257aec26639531d9bfed5ad44cd77c78..535c6a3d300105378fc02c5483ec6f0e265a1071 100644 (file)
@@ -479,7 +479,7 @@ struct CameraDevice::Pimpl  : public ChangeBroadcaster
                     auto context = []\r
                     {\r
                         IBindCtx* ptr = nullptr;\r
-                        ignoreUnused (CreateBindCtx (0, &ptr));\r
+                        [[maybe_unused]] const auto result = CreateBindCtx (0, &ptr);\r
                         return ContextPtr (ptr);\r
                     }();\r
 \r
index 6279cd1861320aa3587aa05199706453acc790e8..263b47e165ac199c8b0b255469d9b2c72833ad0c 100644 (file)
@@ -395,7 +395,7 @@ private:
     {\r
         DirectShowContext (Pimpl& c)  : component (c)\r
         {\r
-            ignoreUnused (CoInitialize (nullptr));\r
+            [[maybe_unused]] const auto result = CoInitialize (nullptr);\r
         }\r
 \r
         ~DirectShowContext() override\r
index 3eb62862bfcf62b2612ada68de63733afaa88b10..10c4138a2f3e5e693396fda7ba0c6c03f72b0f04 100644 (file)
@@ -145,7 +145,6 @@ Result VideoComponent::loadInternal (const FileOrURL& fileOrUrl, bool loadAsync)
 {\r
    #if JUCE_ANDROID || JUCE_IOS\r
     ignoreUnused (fileOrUrl, loadAsync);\r
-\r
     // You need to use loadAsync on Android & iOS.\r
     jassertfalse;\r
     return Result::fail ("load() is not supported on this platform. Use loadAsync() instead.");\r
@@ -155,7 +154,7 @@ Result VideoComponent::loadInternal (const FileOrURL& fileOrUrl, bool loadAsync)
     if (loadAsync)\r
         startTimer (50);\r
     else\r
-       resized();\r
+        resized();\r
 \r
     return result;\r
    #endif\r